Attach document to an email - c#

Is it possible to attach a document to an email without saving it on the server?
The code below is something that attaches only after saving to the server. What I am looking for is to attach the document to the email without having it saved first instead just attach to the email from the path provided.
This is in Visual Studio 2005 using c#
if (SaveDocument.HasFile)
{
/* Get a reference to PostedFile object */
string strFileName = Path.GetFileName(SaveDocument.PostedFile.FileName);
/* Save the file on the server */
SaveDocument.PostedFile.SaveAs(Server.MapPath(strFileName));
/* Create the email attachment with the uploaded file */
System.Net.Mail.Attachment attach = new System.Net.Mail.Attachment(Server.MapPath(strFileName));
/* Attach the newly created email attachment */
message.Attachments.Add(attach);
}

Sure, there's a constructor overload for Attachment which accepts a Stream instead of a file name. So, for example, if you have a byte[] of data, you can create an Attachment from it:
var contentType new ContentType(MediaTypeNames.Text.Plain);
var attach = new Attachment(new MemoryStream(data), contentType);

Yes, just use the constructor that takes a stream rather than a filename.
See:
http://msdn.microsoft.com/en-us/library/ab7hb4y5(v=vs.110).aspx

Pass the PostedFile's InputStream directly to the Attachment.
if (SaveDocument.HasFile)
{
/* Create the email attachment with the uploaded file */
System.Net.Mail.Attachment attach = new System.Net.Mail.Attachment(SaveDocument.PostedFile.InputStream, "filename");
/* Attach the newly created email attachment */
message.Attachments.Add(attach);
}
I haven't tried it yet, but it should work.

Related

failed to add an attachment in MimeMessage (rotativa) for sending Mail

I want to send a (view page) pdf sending by email.but when I trying to add an attachment, I found an error below "Add". for that I can't successfully sending mail with attaching my view pdf.
Here is my code:
(Ordercontroller)
//other code
var message = new MimeMessage();
message.From.Add(new MailboxAddress("Test Project", "pt300#gmail.com"));
message.To.Add(new MailboxAddress("psm", "p689#gmail.com"));
message.Subject = "Hi,this is demo email";
message.Body = new TextPart("plain")
{
Text = "Hello,My First Demo Mail it is.Thanks",
};
//add attach
var aa = new ViewAsPdf("Cart")
{
FileName = "Invoice.pdf", //actually, I don't know why this filename is
// "Invoice". I found this system on a website.
PageOrientation = Rotativa.AspNetCore.Options.Orientation.Portrait,
};
message.Attachments.Add(aa);
//end attach
using (var client = new SmtpClient())
{
client.Connect("smtp.gmail.com", 587, false);
client.Authenticate("pt300#gmail.com", "MyPassword");
client.Send(message);
client.Disconnect(true);
}
//other code
and these controller's view I trying to pdf and send by mail:
(HomeController)
public ActionResult Cart()
{
List<Product> products = HttpContext.Session.Get<List<Product>>("products");
if (products == null)
{
products = new List<Product>();
}
return View(products);
}
in OrderController I found an error.
how I will solve this problem and successfully send my view's pdf by mail.please help.
Attachments is a MimeMessage property that has no such method Add, so here comes the error. To add the attachments you should create a BodyBuilder object before, with this class you will be able to add new attachments (each one of them as byte array), usign Attachments Property and its Add method, but always related to BodyBuilder, not to MimeMessage.
Please, take a look to the answer given here, as I guess is what you are looking for:
.net Core Mailkit send attachement from array
Or check another example here:
https://www.taithienbo.com/send-email-with-attachments-using-mailkit-for-net-core/
In addition, you could get Rotativa PDF as byte array usign this code:
var rotativaAction = new ViewAsPdf("Cart")
{
FileName = "Invoice.pdf", // You can change this file name to set whatever you want
PageOrientation = Rotativa.AspNetCore.Options.Orientation.Portrait,
};
byte[] fileAttachmetByteArray = rotativaAction.BuildFile(ControllerContext);
Once you have generated your PDF as a byte array using Rotativa, guessing you have stored the result in a variable called fileAttachmentByteArray (as stated in the previous code sample), you must simply send this variable (the byte array) to the Add method of the BodyBuilder, as the second parameter (first is the attachement file name, which is completely free to use the name you prefer), and then set Mime Message Body, usign the BodyBuilder you have worked with.
So, to explain the process in steps:
On the first line you create a BodyBuilder variable, and initialize it, using the text you want as body for the email.
Then, you call Add method to add a new attachment, sending to it the file name you wish and your previously created bye array
Finally, you asign the value to the Body property of your Mime Message
And your code should look like this:
var builder = new BodyBuilder { HtmlBody = "yourBodyMessage" }; // Change "yourBodyMessage" to the email body you desire
builder.Attachments.Add("filename", fileAttachmentByteArray); // Once again, you can change this "filename" to set whatever you want
mimeMessage.Body = builder.ToMessageBody(); // Assuming mimeMessage is the same variable you provided in your code

Create attachment from the stream of the data

I am trying to create SendGrid email attachment on-the-fly in C# on Azure. How can I correct the following code where someString is a variable holding the attachment xml content as directly retrieved from the DB?
using (var attachmentFileStream = new FileStream(#someString, FileMode.Open))
{
message.AddAttachment(attachmentFileStream, "someattachmentname.xml");
}
It does not seem to like it. I am getting the following errors:
Illegal characters in path. Access to the path
'D:\Windows\system32-1' is denied.
OK... i think I figured it out. When I pass the stream type into the method I need to strip the "using (var attachmentFileStream..." wrap and pass it directly into the myMessage.AddAttachment i.e.:
// convert to Stream type not MemoryStream!
byte[] byteArray = Encoding.UTF8.GetBytes(someString);
Stream theStream = new MemoryStream(byteArray);
myMessage.AddAttachment(theStream, "someattachmentname.xml");

Sending a csv through email gives me different result than from a file

I have a tabular data that I want to send out using email. I can successfully send and receive the email so that is no problem. The problem is the attachment to the email.
I have attached a csv along with it. The csv is created from a Stream Writer. When I open this file, I get a different result that if I created the file from the stream. If I set the stream position to 0 before adding the stream, the csv file would only write 21/30 lines. If I don't reset the posiiton, it would write no lines. When I look at the file that I created, all the entries seems normal and as expected.
Why is that?
using (FileStream memstream = File.Create(#"C:\Users\home\Desktop\" + "test.csv"))
{
using (StreamWriter writer = new StreamWriter(memstream))
{
data.ForEach(line =>
{
writer.WriteLine(string.Join(",", line));
});
MailMessage message = new MailMessage();
message.To.Add("home#local.com");
message.Subject = "Locations sent to home on " + DateTime.Today.AddDays(-1).ToString("MM-dd-yy");
message.From = new MailAddress("areport#reports.com");
memstream.Position = 0;
Attachment attachment = new Attachment(memstream, "report.csv");
message.Attachments.Add(attachment);
SmtpClient client = new SmtpClient("outbound#out.com");
client.Send(message);
}
}
Most likely your issues are because it's attempting to send the email before you've closed the file stream. Try sending after you've closed the file stream.
As #jtimperley mentioned in the comments your StreamWriter is not being Flushed before you send the email so some contents are not written out.
Calling Flush on the writer should fix it.
writer.Flush();
memstream.Position = 0;
Attachment attachment = new Attachment(memstream, "report.csv");
message.Attachments.Add(attachment);

File are corrupted when Attaching them to MailMessage C#

I have created an application at work that generates exel files from some database data. After generating the files they are sent automatically to the customers in question. My problem is that it works fine when i run the published application. But some users when they run the application the files are generated perfectly as they are saved on the HDD and i can see them. But when they are attached to the MailMessage object they get corrupted. This is an image of the corrupted files. These files should be Excel files.
This is my code for sending a mail with attached files:
public void SendMailedFilesDK()
{
string[] sentFiles = Directory.GetFiles(sentFilesDK);
if (sentFiles.Count() > 0)
{
using (System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient("ares"))
{
using (System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage())
{
msg.From = new MailAddress("system#mail.dk");
msg.To.Add(new MailAddress("operation#mail.dk"));
msg.To.Add(new MailAddress("bl#mail.dk"));
msg.CC.Add("lmy#mail.dk");
msg.CC.Add("ltr#mail.dk");
msg.Subject = "IBM PUDO";
msg.Body = sentFiles.Count() + " attached file(s) has been sent to the customer(s) in question ";
msg.IsBodyHtml = true;
foreach (string file in sentFiles)
{
Attachment attachment = new Attachment(file);
msg.Attachments.Add(attachment);
}
client.Send(msg);
}
}
}
}
Why are the files getting corrupted when others run the application? We are all using office 2010.
You should make sure to set the content type of the attachement to the appropriate value.
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet for xlsx files, or
application/vnd.ms-excel for xls files.
For example, your loop should look something like this.
ContentType xlsxContent = new ContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
foreach (string file in sentFiles)
{
Attachment attachment = new Attachment(file, xlsxContent);
msg.Attachments.Add(attachment);
}
We use this in our Attachment constructor and have no issues attaching Excel and PDF.
Attachment data = new Attachment(sFileName, MediaTypeNames.Application.Octet);
Also check that the users running this have permissions to access the files in whatever location is specified by sentFilesDK.
You might want to specify the mimetype which is part of one of the constructors on Attachment class.
public Attachment(string fileName, ContentType contentType);
You can also read the file in memorystream and pass it as part of the following constructor.
public Attachment(Stream contentStream, string name, string mediaType);

File locked after sending it as attachment

I am sending a file as an attachment:
// Create the file attachment for this e-mail message.
Attachment data = new Attachment(filePath, MediaTypeNames.Application.Octet);
// Add time stamp information for the file.
ContentDisposition disposition = data.ContentDisposition;
disposition.CreationDate = System.IO.File.GetCreationTime(filePath);
disposition.ModificationDate = System.IO.File.GetLastWriteTime(filePath);
disposition.ReadDate = System.IO.File.GetLastAccessTime(filePath);
// Add the file attachment to this e-mail message.
message.Attachments.Add(data);
And then I want to move the file to another folder, however when I try to do this
try
{
//File.Open(oldFullPath, FileMode.Open, FileAccess.ReadWrite,FileShare.ReadWrite);
File.Move(oldFullPath, newFullPath);
}
catch (Exception ex)
{
}
Its throwing an exception that the file is already being used in another process. How I can unlock this file so that it can be moved to this location?
Disposing your message will fix this for you. Try calling Dispose on your message before moving the file, like so:
message.Dispose();
File.Move(...)
When disposing MailMessage, all locks and resources are released.
You need to take advantage of "using" keyword:
using(Attachment att = new Attachment(...))
{
...
}
That's because "using" ensures IDisposable.Dispose method is called at the end of code block execution.
Whenever you use some class that's managing some resource, check if it's IDisposable and then use "using" block and you won't need to care about manually disposing calling IDisposable.Dispose.
Attachments are IDisposable and should be disposed of correctly after they have been sent to release the lock on the file
In order to prevent this file lock from happening, you could use using as this will dispose of the object automatically:
using (Attachment data = new Attachment(filePath, MediaTypeNames.Application.Octet))
{
// Add time stamp information for the file.
ContentDisposition disposition = data.ContentDisposition;
disposition.CreationDate = System.IO.File.GetCreationTime(filePath);
disposition.ModificationDate = System.IO.File.GetLastWriteTime(filePath);
disposition.ReadDate = System.IO.File.GetLastAccessTime(filePath);
// Add the file attachment to this e-mail message.
message.Attachments.Add(data);
// Add your send code in here too
}
Here's another way to dispose of the Attachments, once you've finished with them...
// Prepare the MailMessage "mail" to get sent out...
await Task.Run(() => smtp.Send(mail));
// Then dispose of the Attachments.
foreach (Attachment attach in mail.Attachments)
{
// Very important, otherwise the files remain "locked", so can't be deleted
attach.Dispose();
}
A shared similar problem. I had to use image.dispose() on a given image before I could do something with the file that the image was created from.

Categories