Sending ics file with MailKit and Stringbuilder - c#

I'm trying to send an email with a calendar invite, as an ics file attachment. I'm using Mailkit, as my understanding is the system.net.mail is deprecated.
After playing with it, I understand that the "bodybuilder" is looking for a filepath, but that's not what I'm trying to do here, and so I'm sort of lost.
Alot of the documentation on the web seems to be outdated...
public IActionResult ThrEmail(string sendto, string subject, string body)
{
if (!String.IsNullOrEmpty(sendto))
{
//construct mail
var message = new MimeMessage();
message.From.Add(new MailboxAddress("nick", "nic-fleetwood#behr.travel"));
message.To.Add(new MailboxAddress(sendto));
message.Subject = subject;
//message.Body = new TextPart("plain")
//{
// Text = body
//};
BodyBuilder emailBody = new BodyBuilder();
emailBody.TextBody = body;
//ics file -- use yyyMMddTHHmmssZ format
StringBuilder str = new StringBuilder();
//str.AppendLine()
str.AppendLine("BEGIN:VCALENDAR");
str.AppendLine("PRODID:-//RYNE MOVING//EN");
str.AppendLine("VERSION:2.0");
str.AppendLine("METHOD:PUBLISH");
//THE EVENT
str.AppendLine("BEGIN:VEVENT");
str.AppendLine("DTSTART:20210215T100000");
str.AppendLine("DTEND:20210215T110000");
str.AppendLine("DTSTAMP:" + DateTime.Now);
str.AppendLine("UID:" + Guid.NewGuid());
str.AppendLine("CREATED:" + DateTime.Now);
str.AppendLine("X-ALT-DESC;FMTTYPE=text/html:");
//sb.AppendLine("DESCRIPTION:" + res.Details);
str.AppendLine("LAST-MODIFIED:" + DateTime.Now);
str.AppendLine("LOCATION:NYC");
str.AppendLine("SEQUENCE:0");
str.AppendLine("STATUS:CONFIRMED");
str.AppendLine("SUMMARY:");
str.AppendLine("TRANSP:OPAQUE");
str.AppendLine("END:VEVENT");
str.AppendLine("END:VCALENDAR");
emailBody.Attachments.Add(str.ToString());
//send the email
using (var client = new SmtpClient())
{
client.Connect("smtp.office365.com", 587, false);
// Note: only needed if the SMTP server requires authentication
client.Authenticate("nic-fleetwood#behr.travel", "foobar");
client.Send(message);
client.Disconnect(true);
}
}
return View();
}

AttachmentCollection has several methods to add the specified attachment.
You need to use this one Add(String, Stream):
var emailBody = new BodyBuilder();
var ics = new StringBuilder();
/* initialize calendar options */
using (var stream = new MemoryStream())
{
using (var writer = new StreamWriter(stream))
{
writer.Write(ics.ToString());
writer.Flush();
stream.Position = 0;
emailBody.Attachments.Add("calendar.ics", stream);
}
}
or Add(string, byte[]):
emailBody.Attachments.Add("calendar.ics", Encoding.UTF8.GetBytes(ics.ToString()));

Related

C# Core Builder.Attachments, attach Word but the original file with 1 page after attachment became 4 pages

I am using ASP.NET Core 2.0 and I am trying to attach a Word file into my email. The email is working perfectly, however I had some problems with the attachment.
The original word document has only 1 page, but after being attached and downloaded from the recipient's mail box it started to have 4 pages. Some of text of the 1st page have gone to the 2nd page and in 3rd pages.
Here's my code:
public string TestSend()
{
var webRoot = _hostingEnvironment.WebRootPath;
var pathToFile = "EmailTemplates"
+ Path.DirectorySeparatorChar.ToString()
+ "Test.html";
var builder = new BodyBuilder();
using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
{
builder.HtmlBody = SourceReader.ReadToEnd();
}
string messageBody = string.Format(builder.HtmlBody,
"TEST",
"TEST",
"TEST",
"TEST",
"TEST" );
builder.HtmlBody = messageBody;
builder.Attachments.Add(#"C:\Users\Test\Desktop\Test\Temp.docx");
var message = new MimeMessage();
message.From.Add(new MailboxAddress("Test", Test#test.com));
message.To.Add(new MailboxAddress("Test", JustDemo#test.com));
message.Cc.Add(new MailboxAddress("Test", Test#test.com));
message.Subject = "Test";
message.Body = builder.ToMessageBody();
using (var client = new SmtpClient())
{
client.Connect("smtp.gmail.com", 587, false);
client.Authenticate("test#test.com", "Test");
client.Send(message);
client.Disconnect(true);
}
return "a";
}
Try forcing the Content-Transfer-Encoding to base64:
var attachment = (MimePart) builder.Attachments.Add ("C:\.....");
attachment.ContentTransferEncoding = ContentEncoding.Base64;

Email sending with attachment issue

I am trying to send an email message to different users (with an attachment). The email is being sent, but only one user receives the attachment (image file). Other recipients receive something like empty picture, or picture with name and zero bytes.
I don't really understand what is going wrong. Here is code that I used for sending emails:
public void SendWithFile(string recipientName, string body, string subject = null, HttpPostedFileBase emailFile = null)
{
using (var msg = new MailMessage())
{
msg.To.Add(recipientName);
msg.From = new MailAddress(ConfigurationManager.AppSettings["MailServerSenderAdress"]);
msg.Subject = subject;
msg.Body = body;
msg.SubjectEncoding = Encoding.UTF8;
msg.BodyEncoding = Encoding.UTF8;
msg.IsBodyHtml = true;
msg.Priority = MailPriority.Normal;
using (Attachment data = new Attachment(emailFile.InputStream, Path.GetFileName(emailFile.FileName), emailFile.ContentType))
{
msg.Attachments.Add(data);
using (var client = new SmtpClient())
{
//client configs
try
{
client.Send(msg);
}
catch (Exception ex)
{
throw ex;
}
}
}
}
}
and here is where I call the send email method:
foreach (var recipent in notesRecipients)
{
if (!string.IsNullOrEmpty(userEmail))
{
if (emailFile != null)
emailService.SendWithFile(userEmail, message, null, emailFile);
}
}
You have to seek the stream from the beginning like below before you send the attachment:
emailFile.InputStream.Position = 0;
For more info you can refer to this question here: link

Writing list of strings into Text file adding as attachment to the mail using c#

I am using below code to send an mail with the text file as a attachment and the contents of text file like this "License ADD LOGJz+RC-cVecSpK5-57AOrUlA-6aD3n5Fy-ejFGFIIa-XPU"
public static bool sendMailFromToCCSubMsgAttachment(string fromName, string fromAdd, string toline, string subj, string htmlmsg, string cc, string strAttachment)
{
SmtpClient smtpClient = new SmtpClient(ConfigurationSettings.AppSettings["MAIL_SERVER"], Int32.Parse(ConfigurationSettings.AppSettings["SERVER_PORT"]));
MailMessage mail = new MailMessage();
if (!string.IsNullOrEmpty(strAttachment))
{
ContentType ct = new ContentType();
ct.MediaType = MediaTypeNames.Text.Plain;
Attachment attachFile = Attachment.CreateAttachmentFromString(strAttachment, ct);
mail.Attachments.Add(attachFile);
}
.........
.........
..........
}
Here We are passing above content in "strAttachment" variable to this method
now i am looking to pass list of strings as contents to that text file and the content format like this below..
License ADD 2N674h5A-cVc9XiCG-N0TChPo3-mRVmOtUm-GYup9evK-3d4
License ADD VljH169B-cVe22hrW-U/HMICqW-1aeB5pJE-YpZIOThd-eBc
License ADD FIsc70dC-cVeVN9Ed-J833n4q4-vyMgnOXM-HjsMKrhT-qy0
License ADD LOGJz+RC-cVecSpK5-57AOrUlA-6aD3n5Fy-ejFGFIIa-XPU
How can i add these list of strings as contents to the text file using above code snippet ..
Would any one please help on this ..
Many thanks in advance....
Change input parameter to List<string> and inside method create a string variable to hold Those string separated by Newline, write these to your attachment file.
Like this
public static bool sendMailFromToCCSubMsgAttachment(string fromName, string fromAdd, string toline, string subj, string htmlmsg, string cc, List<string> strAttachment)
{
SmtpClient smtpClient = new SmtpClient(ConfigurationSettings.AppSettings["MAIL_SERVER"], Int32.Parse(ConfigurationSettings.AppSettings["SERVER_PORT"]));
MailMessage mail = new MailMessage();
string strAttachmentboyd = string.Join(Environment.NewLine, strAttachment);
// your other code
}
This is the code I use for attaching a file into an email.
public static void sendMailWithAttachment(string strAttachment)
{
//insert the licence into a memorystream.
//Note not using the 'using' statement with the MemoryStream and StreamWriter.
//If you do you will get a 'cannot access a closed stream' error when attaching the stream into the email
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(strAttachment);
writer.Flush();
stream.Position = 0;
//start the mail sending
using (SmtpClient client = new SmtpClient())
using (MailMessage oMail = new MailMessage())
{
//mail config settings
client.Port = 25;
client.Host = "localhost";
client.Timeout = 30000;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential("userName", "passWord");
//mail content stuff
oMail.From = new MailAddress("fake#false.nl", "yourName");
oMail.To.Add(new MailAddress("fake#false.nl"));
oMail.Subject = "Your Licence";
oMail.IsBodyHtml = true;
oMail.Body = "<html><head></head><body> Hello </body></html>";
//insert the text file as attatchment from the stream
if (!string.IsNullOrEmpty(strAttachment))
{
oMail.Attachments.Add(new Attachment(stream, "Licence.txt", "text/plain"));
}
//send the mail
client.Send(oMail);
}
//dispose the stream and writer containing the license
writer.Dispose();
stream.Dispose();
}

attach a pdf in an email using SelectPdf .NET without saving PDF

I am using SelectPdf to convert a HTML to PDF and sending the PDF in an email without saving it and putting into a MemoryStream, but the email is never sent
If I create an Email without attaching the PDF is always sent.
Here my code:
public void SendEmail(string htmlBody, string email, string emailBody, string subject)
{
PdfDocument doc = null;
try
{
//Reading the html and converting it to Pdf
HtmlToPdf pdf = new HtmlToPdf();
doc = pdf.ConvertHtmlString(htmlBodyReservaPasajeros);
var streamPdf = new MemoryStream(doc.Save());
//creating the message
message.From = new MailAddress(ConfigurationManager.AppSettings[url + "Email"]);
message.To.Add(new MailAddress(email));
message.Subject = subject;
message.Body = HtmlBody;
message.IsBodyHtml = true;
if (doc != null)
{
message.Attachments.Add(new Attachment(streamPdf , "Prueba.pdf", "application/pdf"));
}
//Sending the email
...
//Closing
streamPdf.Close();
doc.Close();
}
catch (Exception e)
{
}
}
UPDATE
I had two problems:
First: gmail recognized the email as span, but...
Second:Even so I had to write doc.DetachStream() since the pdf was corrupted.
This function detach the object memoryStream from PdfDocument and set it free.
in the end the code is the next:
public void SendEmail(string htmlBody, string email, string emailBody, string subject)
{
PdfDocument doc = null;
try
{
//Reading the html and converting it to Pdf
HtmlToPdf pdf = new HtmlToPdf();
doc = pdf.ConvertHtmlString(htmlBodyReservaPasajeros);
var streamPdf = new MemoryStream(doc.Save());
**doc.DetachStream();**
//creating the message
message.From = new MailAddress(ConfigurationManager.AppSettings[url + "Email"]);
message.To.Add(new MailAddress(email));
message.Subject = subject;
message.Body = HtmlBody;
message.IsBodyHtml = true;
if (doc != null)
{
message.Attachments.Add(new Attachment(streamPdf , "Prueba.pdf", "application/pdf"));
}
//Sending the email
...
//Closing
streamPdf.Close();
doc.Close();
}
catch (Exception e)
{
}
}
This Code worked for me.. !
public void SendEmail(string htmlBody, string email, string emailBody, string subject)
{
try
{
//Reading the html and converting it to Pdf
HtmlToPdf pdf = new HtmlToPdf();
PdfDocument doc = pdf.ConvertHtmlString(htmlBodyReservaPasajeros);
using (MemoryStream memoryStream = new MemoryStream())
{
doc.Save(memoryStream);
byte[] bytes = memoryStream.ToArray();
memoryStream.Close();
MailMessage message= new MailMessage();
message.From = new MailAddress(
ConfigurationManager.AppSettings[url + "Email"]
);
message.To.Add(new MailAddress(email));
message.Subject = subject;
message.Body = htmlBody;
message.IsBodyHtml = true;
message.Attachments.Add(new Attachment(
new MemoryStream(bytes),
"Prueba.pdf"
));
//Sending the email
. . .
}
doc.Close();
}
catch (Exception e)
{
// handle Exception
. . .
}
}
Check to see of the generated memory stream has the current position at the beginning. You might need to set something like this:
streamPdf.Position = 0;

Attach file from internet to mail without saving it in disk in asp.net

I've written a mail sending code for asp.net. it is working fine. I can attach files that are saved on disk. Now I want to attach a file that is on the internet. I can download the file and save it somewhere on disk and attach the file. but I don't want to save the file on disk. I just need to download the file in memory and attach it to my mail. need help to do that.
here is my code for sending email
public void SendMail(string To, string Subject, string Body)
{
MailMessage mail = new MailMessage();
mail.From = new MailAddress("noreply#xyz.com", "xyz");
mail.To.Add(new MailAddress(To));
mail.Subject = Subject;
mail.Body = Body;
mail.IsBodyHtml = true;
using (SmtpClient smtpClient = new SmtpClient())
{
try
{
smtpClient.Send(mail);
}
catch (Exception ex)
{
throw ex;
}
}
}
I want some thing like this
public void SendMail(string To, string Subject, string Body, URI onlineFileURI)
{
MailMessage mail = new MailMessage();
mail.From = new MailAddress("noreply#xyz.com", "xyz");
mail.To.Add(new MailAddress(To));
mail.Subject = Subject;
mail.Body = Body;
mail.IsBodyHtml = true;
//Create the attachment from URL
var attach = [Attachemnt from URL]
mail.Attachments.Add(attach)
using (SmtpClient smtpClient = new SmtpClient())
{
try
{
smtpClient.Send(mail);
}
catch (Exception ex)
{
throw ex;
}
}
}
How I can download the file in memory and attach it?
This is how I ended up doing it based of previous posts:
var url = "myurl.com/filename.jpg"
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
using (HttpWebResponse HttpWResp = (HttpWebResponse)req.GetResponse())
using (Stream responseStream = HttpWResp.GetResponseStream())
using (MemoryStream ms = new MemoryStream())
{
responseStream.CopyTo(ms);
ms.Seek(0, SeekOrigin.Begin);
Attachment attachment = new Attachment(ms, filename, MediaTypeNames.Image.Jpeg);
message.Attachments.Add(attachment);
_smtpClient.Send(message);
}
You can do it by converting page into Stream/byte array and send it
Here is the code
string strReportUser = "RSUserName";
string strReportUserPW = "MySecretPassword";
string strReportUserDomain = "DomainName";
string sTargetURL = "http://SqlServer/ReportServer?" +
"/MyReportFolder/Report1&rs:Command=Render&rs:format=PDF&ReportParam=" +
ParamValue;
HttpWebRequest req =
(HttpWebRequest)WebRequest.Create( sTargetURL );
req.PreAuthenticate = true;
req.Credentials = new System.Net.NetworkCredential(
strReportUser,
strReportUserPW,
strReportUserDomain );
HttpWebResponse HttpWResp = (HttpWebResponse)req.GetResponse();
Stream fStream = HttpWResp.GetResponseStream();
HttpWResp.Close();
//Now turn around and send this as the response..
ReadFullyAndSend( fStream );
ReadFullyAnd send method. NB: the SendAsync call so your not waiting for the server to send the email completely before you are brining the user back out of the land of nod.
public static void ReadFullyAndSend( Stream input )
{
using ( MemoryStream ms = new MemoryStream() )
{
input.CopyTo( ms );
MailMessage message = new MailMessage("from#foo.com", "too#foo.com");
Attachment attachment = new Attachment(ms, "my attachment",, "application/vnd.ms-excel");
message.Attachments.Add(attachment);
message.Body = "This is an async test.";
SmtpClient smtp = new SmtpClient("localhost");
smtp.Credentials = new NetworkCredential("foo", "bar");
smtp.SendAsync(message, null);
}
}
courtesy:Get file to send as attachment from byte array

Categories

Resources