This question already has answers here:
Adding an attachment to email using C#
(5 answers)
Closed 4 years ago.
I'm trying to add an attachment to an email I'm sending through my program but I'm getting the error referenced above.
I'm saving images taken during run time, and adding the name to a List which is called ImageFilenames. I'm then using the following code to retrieve the files and add them as an attachment, but I can't seem to figure out what I need to do to get this working.
SaveScreenshots();
using (MemoryStream stream = new MemoryStream())
{
using (SmtpClient SmtpServer = new SmtpClient())
{
using (MailMessage mail = new MailMessage())
{
mail.From = new MailAddress("*****.******#******.com");
mail.To.Add("******#*****.com");
mail.Subject = this.Summary;
mail.Body = this.ToString();
SmtpServer.Port = ***;
foreach (string file in ImageFilenames)
{
var images = Directory.GetFiles(file);
mail.Attachments.Add(images);
//I tried this and the below method with no success
mail.Attachments.Add(Directory.GetFiles(file));
}
SmtpServer.Credentials = new System.Net.NetworkCredential("******#****.com", "********");
SmtpServer.EnableSsl = false;
SmtpServer.Host = "*****-1";
SmtpServer.Send(mail);
}
}
}
}
ClearScreenCaptures();
}
Any help would be appreciated. Thank you!
Edit: Thank you for the suggested related question, but I am aware of how to add an attachment. My question was specifically how to do this using a list of filenames. Thank you though!
Directory.GetFiles(file);
Returns a string array, you'll need to create an Attachment object. Something like this:
var attachment = new Attachment(filePath));
Try this
Directory.GetFiles(file).ToList()
.ForEach(t => x.Attachments.Add(new Attachment(t)));
Related
I am trying to add a picture to the mail I am sending in C#, and I found some code in here - stackoverflow. (the question: Add Attachment base64 image in MailMessage and read it in html body).
but this code is giving me syntax errors in C# I don't know how to solve correctly... here is my code:
using System.Net.Mail;
using System.Net.Mime;
public static string FixBase64ForImage(string Image)
{
System.Text.StringBuilder sbText = new System.Text.StringBuilder(Image, Image.Length);
sbText.Replace("\r\n", string.Empty); sbText.Replace(" ", string.Empty);
return sbText.ToString();
}
public static bool SendEmail2(string mailToGet, string subject, string message, string image)
{
try
{
Byte[] bitmapData = Convert.FromBase64String(FixBase64ForImage(image));
System.IO.MemoryStream streamBitmap = new System.IO.MemoryStream(bitmapData);
MailMessage mail = new MailMessage();
var imageToInline = new LinkedResource(streamBitmap, MediaTypeNames.Image.Jpeg);
imageToInline.ContentId = "MyImage";
alternateView.LinkedResources.Add(imageToInline);//here there is an error
mail.AlternateViews.Add(body);//here there is an error
//from now on - my code:
SmtpClient SmtpServer = new SmtpClient("smtp.gmail.com");
mail.IsBodyHtml = true;
message+= "<img alt ='' src ='cid: MyImage'/>";
mail.Body = message;
mail.Subject = subject;
mail.To.Add(mailToGet);
SmtpServer.Port = 587;
SmtpServer.Credentials = new System.Net.NetworkCredential("myEmailAdress", "myPassword");
SmtpServer.EnableSsl = true;
SmtpServer.Send(mail);
return true;
}catch(Exception e)
{
throw e;
}
}
I have two errors: one on line alternateView.LinkedResources.Add(imageToInline);, where it says: The name 'alternateView' does not exist in the current context, and one on line mail.AlternateViews.Add(body);, where it gives the same - on the body.
I tried creating these elements here, but it only got me into more trouble... I don't even know if I am using the right usings (by the way, I put these by the demand of C#, not as part of the code I copied). Can anyone tell me what this code means and where I was wrong? and if you know, what should I do to repair this?
Firstly, your alternateView does not exist because you did not instanciate it, to do this you need to add this line before:
AlternateView alternateView = new AlternateView("MyImage");
Where "MyImage" is the name of the file. And in regards to the body error you need to add that alternating view that you just created, so instead of "body" you just need to put alternateView like so:
mail.AlternateViews.Add(alternateView);
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
This seems like a tough one to find a good answer to. I want to create a mail message, add attachments to it, encrypt it using a X509Certificate2 certificate, and then send it. Sounds simple enough, right?! I use asp.net mvc and C#.
This is what I have so far.
string sMTPClient = ConfigurationManager.AppSettings.Get("SMTPClient");
using (var smtpClient = new SmtpClient(sMTPClient))
{
var attachments = MethodToCreateMailAttachments(......);
X509Certificate2 certificate = MethodToGetCertificateBySerialNumber("xxxxxxx");
using (var finalMailmessage = new MailMessage())
{
var encryptedMailMessage = new MailMessage();
var encryptCert = new X509Certificate2(certificate);
encryptedMailMessage.Subject = mailsubject;
encryptedMailMessage.Body = mailBody;
if (attachments.Any())
{
foreach (var item in attachments)
encryptedMailMessage.Attachments.Add(item);
}
byte[] encryptedBodyBytes = Encoding.ASCII.GetBytes(encryptedMailMessage.ToString());
EnvelopedCms Envelope = new EnvelopedCms(new ContentInfo(encryptedBodyBytes));
CmsRecipient Recipient = new CmsRecipient(SubjectIdentifierType.IssuerAndSerialNumber, encryptCert);
Envelope.Encrypt(Recipient);
byte[] EncryptedBytes = Envelope.Encode();
//Attach the encrypted message as an alternate view.
MemoryStream ms = new MemoryStream(EncryptedBytes);
AlternateView av = new AlternateView(ms, "application/pkcs7-mime; smime-type=signed-data;name=smime.p7m");
finalMailmessage.AlternateViews.Add(av);
finalMailmessage.From = new MailAddress(mailFrom);
foreach (var address in mailTo.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries))
{
finalMailmessage.To.Add(address);
}
var smtp = new SmtpClient(sMTPClient);
smtp.Send(finalMailmessage);
finalMailmessage.Dispose();
ErrorLogging.log.Debug("Mailmessage sent");
return "";
}
}
What this does is create two MailMessages, one for the things that need to be encrypted, attachments, body and subject. Then I create the message that will be sent. To this I add the first message as an alternate view. This works so far as to encrypt and send the email, and on the recieving end, I get an email with a padlock icon in Outlook.
I can then open the message in Outlook, by importing the certificate. This works. However, next to the padlock icon, in Outlook, I get the attachment paperclip icon, which suggests that there is something attached to the message. But the message is empty. So nothing gets attached apparently. I suspect the adding of the encrypted MailMessage as an alternate view to the other MailMessage, is where I have gone wrong.
I've tried a lot of other things with no luck, and this is the closest I have come to a working solution. I need some input, so does anyone have any suggestions?
I found a working solution. The problem was this part:
byte[] encryptedBodyBytes = Encoding.ASCII.GetBytes(encryptedMailMessage.ToString());
I had to create a memorystream, which can then be converted into a byte array. I used a tool called "MimeKit", which can be installed as a nuget package.
So, instead I have:
var memStream = new MemoryStream();
var mimeMessage = MimeMessage.CreateFromMailMessage(encryptedMailMessage);
mimeMessage.WriteTo(memStream);
var messageString = Encoding.UTF8.GetString(memoryStream.ToArray());
byte[] encryptedBodyBytes = Encoding.ASCII.GetBytes(messageString);
The rest is the same.
I'm trying to send an email and it should display subject line like below.
I tried to put image in subject line but it won't work.
I also googling but unable to find any solution.
Is anyone know how to do it ?
Thank you.
That's an Emoji.
With the coolness of emoji, a new markting boom is adding emojis to the subject lines of email.
It´s not possible to add your own custom images to the subject line.
https://www.campaignmonitor.com/resources/guides/using-emojis-and-symbols-in-email-marketing/
Creating an email message using UTF-8
https://msdn.microsoft.com/en-us/library/system.net.mail.mailmessage.bodyencoding%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
List of unicode Emojis
http://unicode.org/emoji/charts/full-emoji-list.html
As you know by now, you're referencing an emoji. But I just want to share that my own experience using emojis in C# for sending gmail does not require any conversion to UTF8.
In the link provided by Webbanditten, this is presented for the sake of producing some arrows:
MailMessage message = new MailMessage(from, to);
message.Body = "This is a test email message sent by an application. ";
// Include some non-ASCII characters in body and subject.
string someArrows = new string(new char[] {'\u2190', '\u2191', '\u2192', '\u2193'});
message.Body += Environment.NewLine + someArrows;
message.BodyEncoding = System.Text.Encoding.UTF8;
message.Subject = "test message 1" + someArrows;
message.SubjectEncoding = System.Text.Encoding.UTF8;
I don't know if its because I'm working on a .cs file that's saved as UTF-8 already, but I can just cut and paste emojis right in and don't have do deal with SubjectEncoding or with character codes.
A modified version of the code below runs successfully and both notepad and visual studio display the actual emoji in the code so it's 'readable'.
var hasIssues = true;
var emoji = hasIssues ? "😡" : "👍";
using (var client = new SmtpClient("host"))
using (var mail = new MailMessage()) {
mail.From = new MailAddress("name#from.com");
mail.To.Add("name#to.com);
mail.Subject = $"{emoji} Emoji Test";
mail.Body = "Did it go well? Check the emoji on the subject line";
client.Send(mail);
}
What I want to achieve:
Scan mails and attach relevant ones to a "summary"-mail.
My problem:
I can't seem to find any information about how this is done. When using for example Outlook you can simply drag and drop a mail into another message thus attaching it. I looked through the headers and found that it's basically the mail's content and attachments with their content types attached without further encoding. But attaching this data to a MailMessage via Attachment.CreateAttachmentFromString didn't work out either, the file was displayed as a regular file.
My current code:
var mail = new MailMessage(settings.Username, to);
var smtp = new SmtpClient(settings.SMTP, settings.Port);
// ...
// authentication + packing stuff into subject and body
// ...
foreach (var att in attachments)
{
Attachment attachment = Attachment.CreateAttachmentFromString(att.Text, att.Filename);
mail.Attachments.add(attachment);
}
client.Send(mail);
client.Dispose();
mail.Dispose();
My question:
Can C# do this out of the box using some hack or are there libraries that support that?
You would probably want to just use the Attachment constructor that takes a file name:
Attachment attachment = new Attachment(att.Filename);
mail.Attachments.add(attachment);
Of course, this assumes you've saved the attachment already out to your file system somewhere.
You could also just use the attachment's content stream to avoid the overhead of saving each attachment to file first:
Attachment attachment = new Attachment(att.ContentStream, String.Empty);
mail.Attachments.add(attachment);
NOTE: the second argument to that constructor is the "content type", which, if left as an empty string, will be text/plain; charset=us-ascii. Refer to RFC 2045 Section 5.1 for more content types.
Also, see MSDN for more Attachment constructor overloads: https://msdn.microsoft.com/en-us/library/System.Net.Mail.Attachment.Attachment%28v=vs.110%29.aspx
Well, I found a way to somehow does what I needed. This solution is not the perfect answer, but it works almost as intended.
Warning
This solution requires currently Outlook installed as the mail needs to be attached as a .msg file. I want to repeat that this is not the right way to go, this method is way slower than any other solution but it works. I will further investigate soon.
But for now, here's my Extension class:
using System;
using System.Net.Mail;
using System.IO;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace MailAttachment
{
public static class Extensions
{
public static string AttachMail(this MailMessage mail, MailMessage otherMail)
{
string path = Path.GetTempPath(),
tempFilename = Path.Combine(path, Path.GetTempFileName());
Outlook.Application outlook = new Outlook.Application();
Outlook.MailItem outlookMessage;
outlookMessage = outlook.CreateItem(Outlook.OlItemType.olMailItem);
foreach (var recv in message.To)
{
outlookMessage.Recipients.Add(recv.Address);
}
outlookMessage.Subject = mail.Subject;
if (message.IsBodyHtml)
{
outlookMessage.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
outlookMessage.HTMLBody = message.Body;
}
else
{
outlookMessage.Body = message.Body;
}
outlookMessage.SaveAs(tempFilename);
outlookMessage = null;
outlook = null;
Attachment attachment = new Attachment(tempFilename);
attachment.Name = mail.Subject + ".msg";
otherMail.Attachments.Add(attachment);
return tempFilename;
}
}
}
Additional information
This solution requires you to delete the temporary file after you sent the mail. This might look like this:
MailMessage mail = new MailMessage();
List<MailMessage> mailsToAttach = mails.FindAll(m => m.Date.CompareTo(otherDate) < 0);
List<string> tempFiles = new List<string>();
foreach (var item in mailsToAttach)
{
string tempFile = mail.AttachMail(item);
tempFiles.Add(tempFile);
}
// smtp.Send(mail)
foreach (var item in tempFiles)
{
System.IO.File.Delete(item);
}