How to Send a MimeMessage - c#

May I know how can I send out a MimeMessage?
Below is my code snippet:
MimeMessage eml = MimeMessage.Load(savedEmlFullFilePath);
MimeMessage toSend = Reply(eml,true); //to send out this message
public static MimeMessage Reply(MimeMessage message, bool replyToAll)
{
var reply = new MimeMessage();
// reply to the sender of the message
if (message.ReplyTo.Count > 0)
{
reply.To.AddRange(message.ReplyTo);
}
else if (message.From.Count > 0)
{
reply.To.AddRange(message.From);
}
else if (message.Sender != null)
{
reply.To.Add(message.Sender);
}
if (replyToAll)
{
reply.To.AddRange(message.To);
reply.Cc.AddRange(message.Cc);
}
// set the reply subject
if (!message.Subject.StartsWith("Re:", StringComparison.OrdinalIgnoreCase))
reply.Subject = "Re:" + message.Subject;
else
reply.Subject = message.Subject;
// construct the In-Reply-To and References headers
if (!string.IsNullOrEmpty(message.MessageId))
{
reply.InReplyTo = message.MessageId;
foreach (var id in message.References)
reply.References.Add(id);
reply.References.Add(message.MessageId);
}
// quote the original message text
using (var quoted = new StringWriter())
{
var sender = message.Sender ?? message.From.Mailboxes.FirstOrDefault();
quoted.WriteLine("On {0}, {1} wrote:", message.Date.ToString("f"), !string.IsNullOrEmpty(sender.Name) ? sender.Name : sender.Address);
using (var reader = new StringReader(message.TextBody))
{
string line;
while ((line = reader.ReadLine()) != null)
{
quoted.Write("> ");
quoted.WriteLine(line);
}
}
reply.Body = new TextPart("plain")
{
Text = quoted.ToString()
};
}
return reply;
}
Edit: Would also like to know if it is possible to parse in a MimeMessage into an EmailMessage to I can send it as a ResponseMessage using EWS...

From the MailKit README:
using (var client = new SmtpClient ()) {
// For demo-purposes, accept all SSL certificates (in case the server supports STARTTLS)
client.ServerCertificateValidationCallback = (s,c,h,e) => true;
client.Connect ("smtp.server.com", 587, false);
// Note: only needed if the SMTP server requires authentication
client.Authenticate ("username", "password");
client.Send (message);
client.Disconnect (true);
}

Related

FileStream Attachment To Email C#

I wrote a code to make attachments for email sending, but I cannot understand how to make it not only for txt files. I know that all the binary files are broken because of "File.OpenText" in my code. Someone can explain to me, how to make it for all files, not only for txt.
public async Task<ResponseData> SendEmail(VictimData victimData, SmtpData senderData, LetterData letter)
{
ResponseData response = new ResponseData();
BodyBuilder bodyBuilder = new BodyBuilder();
string newAttachment = "";
try
{
MimeMessage message = new MimeMessage();
message.From.Add(new MailboxAddress(senderData.senderName, senderData.senderEmail));
message.To.Add(new MailboxAddress("", victimData.email));
/*message.Bcc.Add(new MailboxAddress(senderData.senderName, senderData.senderEmail));
message.ReplyTo.Add(new MailboxAddress(senderData.senderName, senderData.senderEmail));*/
message.Subject = letter.subject;
if (letter.isHtml)
{
bodyBuilder.HtmlBody = letter.body;
}
else
{
bodyBuilder.TextBody = letter.body;
}
foreach (var attachment in letter.attachment)
{
newAttachment = ReadAndReplaceAttachment(attachment.filePath, victimData.email, attachment.fileName);
bodyBuilder.Attachments.Add(newAttachment);
File.Delete(newAttachment);
Console.WriteLine(newAttachment);
}
message.Body = bodyBuilder.ToMessageBody();
await client.SendAsync(message);
response.status = true;
response.messages = "";
return response;
}
catch (Exception ex)
{
response.messages = ex.Message;
response.status = false;
return response;
}
}
private string ReadAndReplaceAttachment(string filePath, string email, string newFileName)
{
Replacer replacer = new Replacer();
string tempFile = Path.Combine(Helpers.tempPath, replacer.DoReplace(newFileName, email));//Path.GetTempPath() + Guid.NewGuid().ToString() + Path.GetExtension(filePath);
string contentResult = "";
using (StreamReader sr = File.OpenText(filePath))
{
contentResult = sr.ReadToEnd();
contentResult = replacer.DoReplace(contentResult, email);
sr.Close();
}
using (var tw = new StreamWriter(tempFile, true))
{
tw.Write(contentResult);
}
return tempFile;
}
You would need to change your code to only call your ReadAndReplaceAttachment() method for txt files and not for any other type of file. For non-text files, you would just attach the original file referenced by attachment.filePath.

Exception during delete file attached to a sent email

After successfully sending email with attachment I have to delete files I've sent as attachement.
Files are in use so I have an exception.
I've used the code of the documentation. I'm using a method to create and send the email so everything is disposed automatically after calling it.
MimeMessage eMail = new MimeMessage();
eMail.From.Add (new MailboxAddress(fromDescription, fromAddress));
foreach (string to in toAddress)
eMail.To.Add(new MailboxAddress(to));
if (ccAddress != null)
foreach (string cc in ccAddress)
eMail.Cc.Add(new MailboxAddress(cc));
if (ccnAddress != null)
foreach (string ccn in ccnAddress)
eMail.Bcc.Add(new MailboxAddress(ccn));
eMail.Subject = subject;
var Body = new TextPart("plain")
{
Text = body
};
// now create the multipart/mixed container to hold the message text and the attachment
var multipart = new Multipart("mixed");
multipart.Add(Body);
if (attachments != null)
{
foreach (string attachmentPath in attachments)
{
// create an attachment for the file located at path
var attachment = new MimePart(MimeTypes.GetMimeType(attachmentPath))
{
Content = new MimeContent(File.OpenRead(attachmentPath), ContentEncoding.Default),
ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),
ContentTransferEncoding = ContentEncoding.Base64,
FileName = Path.GetFileName(attachmentPath)
};
multipart.Add(attachment);
}
}
// now set the multipart/mixed as the message body
eMail.Body = multipart;
using (var client = new SmtpClient())
{
// For demo-purposes, accept all SSL certificates (in case the server supports STARTTLS)
//client.ServerCertificateValidationCallback = (s, c, h, e) => true;
client.Connect(SmtpHost, SmtpPort, SecureSocketOptions.SslOnConnect);
// Note: since we don't have an OAuth2 token, disable
// the XOAUTH2 authentication mechanism.
//client.AuthenticationMechanisms.Remove("XOAUTH2");
// Note: only needed if the SMTP server requires authentication
client.Authenticate(SmtpUser, SmtpPassword);
client.Send(eMail);
client.Disconnect(true);
}
What's wrong? Anyoone could help me?
Thank you
You need to dispose the stream you opened for the attachment:
File.OpenRead(attachmentPath)
You could do something like this:
var streams = new List<Stream> ();
if (attachments != null) {
foreach (string attachmentPath in attachments) {
// create an attachment for the file located at path
var stream = File.OpenRead(attachmentPath);
var attachment = new MimePart(MimeTypes.GetMimeType(attachmentPath)) {
Content = new MimeContent(stream, ContentEncoding.Default),
ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),
ContentTransferEncoding = ContentEncoding.Base64,
FileName = Path.GetFileName(attachmentPath)
};
multipart.Add(attachment);
streams.Add (stream);
}
}
And then, after sending the message, do this:
foreach (var stream in streams)
stream.Dispose ();

Cannot send email from server

I am trying to make a .net core application that send me an email from an URL.
It works perfectly in my local machine but when i deploy it to my server IIS throws me the next exception:
Insufficient system storage. The server response was: 4.3.1 Insufficient system resources
I don't have this exception when i test it on my machine and the email send correctly, only in the IIS Server is there any configuration that my server need?
here is my code:
MailController.cs
[EnableCors("MyPolicy")]
[Produces("application/json")]
[Route("api/Mail")]
public class MailController : Controller
{
[HttpPost("Send")]
public string Send([FromBody]Correo mail)
{
try
{
MailMessage data = new MailMessage();
data.Body = mail.Body;
if (mail.BodyEncoding != null)
data.BodyEncoding = mail.BodyEncoding;
data.BodyTransferEncoding = mail.BodyTransferEncoding;
data.DeliveryNotificationOptions = mail.DeliveryNotificationOptions;
if (mail.HeadersEncoding != null)
data.HeadersEncoding = mail.HeadersEncoding;
data.Priority = mail.Priority;
if (mail.SubjectEncoding != null)
data.SubjectEncoding = mail.SubjectEncoding;
if (mail.Headers != null)
foreach (NameValueCollection header in mail.Headers)
{
data.Headers.Add(header);
}
if (mail.Attachments != null)
foreach (String att in mail.Attachments)
{
Attachment attachment = new Attachment(att);
data.Attachments.Add(attachment);
}
if (mail.CC != null)
foreach (String cc in mail.CC)
{
data.CC.Add(cc);
}
data.From = new MailAddress(mail.From);
data.IsBodyHtml = mail.IsBodyHtml;
data.Subject = mail.Subject;
foreach (String to in mail.To)
{
data.To.Add(to);
}
SmtpClient smtp = new SmtpClient("<IP of SMTP server>");
smtp.UseDefaultCredentials = true;
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
smtp.Send(data);
data.Dispose();
return "Done!";
}
catch (Exception e)
{
return "Mail not send: " + e.Message;
}
}
}
also i send this from an HttpClient from any other code...
AuthOController.cs - Recovery method
[HttpPost("Recovery/{userName}")]
public async Task<IActionResult> Recovery(String userName)
{
try
{
Correo sender = new Correo();
...
...
...
var myContent = JsonConvert.SerializeObject(sender);
var buffer = Encoding.UTF8.GetBytes(myContent);
var byteContent = new ByteArrayContent(buffer);
byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpClient httpClient = new HttpClient();
var result = await httpClient.PostAsync("http://MailSender/api/Mail/Send", byteContent);
var contents = await result.Content.ReadAsStringAsync();
}
return Ok("Done!");
}
catch (Exception e)
{
return BadRequest(Errors.AddErrorToModelState("recovery_failure", "There was an error in the service: " + e.Message, ModelState));
}
}
data.From = new MailAddress(mail.From);
this line create new object, Change this
For detail help check here

Send email using Html template with MailKit in .net core application

I am sending an email from .net core application using MailKit, and it will sent it successfully.
But I want to use HTML template to send email with MailKit in .Net core.
Here are the code currently sending email with static body part
var emailMessage = new MimeMessage();
if (!string.IsNullOrWhiteSpace(cc))
{
emailMessage.Cc.Add(new MailboxAddress(cc));
}
else if (!string.IsNullOrWhiteSpace(EmailUserNameCC))
{
emailMessage.Cc.Add(new MailboxAddress(EmailUserNameCC));
}
if (!string.IsNullOrWhiteSpace(EmailUserNameBCC))
{
emailMessage.Bcc.Add(new MailboxAddress(EmailUserNameBCC));
}
emailMessage.From.Add(new MailboxAddress(mailFrom));
emailMessage.To.Add(new MailboxAddress(mailTo));
emailMessage.Subject = subject;
if (!string.IsNullOrWhiteSpace(replyTo))
{
emailMessage.InReplyTo = replyTo;
}
var builder = new BodyBuilder();// { TextBody = message };
builder.HtmlBody = message;
if (attachments != null && attachments.Count > 0)
{
foreach (var item in attachments)
{
builder.Attachments.Add(item.Key, item.Value);
}
builder.HtmlBody = builder.HtmlBody + " \n" + " PFA";
}
var multipart = new Multipart("mixed");
multipart.Add(new TextPart("html") { Text = message });
emailMessage.Body = builder.ToMessageBody();
using (var client = new SmtpClient())
{
var credentials = new NetworkCredential
{
UserName = EmailUserName,
Password = EmailPassword
};
if (!client.IsConnected)
{
client.Connect(SmtpHost, Convert.ToInt32(EmailHostPort));
client.Authenticate(EmailUserName, EmailPassword);
}
client.MessageSent += c_EmailReached;
client.Send(emailMessage);
}
Now, I want to use HTML template to replace body part.
So how can I use HTML Template with MailKit in .Net Core ?
Additional:
-> Also the special characters are not showing in actual email after sending email with html template. For some special characters it is displaying � . So how can I resolved this, to show special characters also.
Thanks.
You can use StreamReader to read the source file and assign it to your builder.HtmlBody.
using (StreamReader SourceReader = System.IO.File.OpenText(path to your file))
{
builder.HtmlBody = SourceReader.ReadToEnd();
}

Auto flush of tcp stream doesn't work

As you may see I work a little SMTP server written in C#.
I included whole code (one class is not included), but I hope you get good view of detail.
I am struggeling at the DATA post from the client, the problem is in my point of view the not working "Auto Flush".
The client sends to my server "DATA" to tell me to get ready to receive data for my email.
I need to answer "354 start mail input", which I do, my problem is:
After sending "354 start mail input" I need to receive the message from client in this funtion.
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace FakeSMTP
{
public class SMTPServer //: IDisposable
{
TcpClient client;
NetworkStream stream;
System.IO.StreamReader reader;
System.IO.StreamWriter writer;
//public void Dispose()
//{
// writer.Dispose();
// reader.Dispose();
// stream.Dispose();
//}
public SMTPServer(TcpClient client)
{
this.client = client;
stream = client.GetStream();
reader = new System.IO.StreamReader(stream);
writer = new System.IO.StreamWriter(stream);
writer.NewLine = "\r\n";
writer.AutoFlush = true;
}
static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Loopback, 25);
listener.Start();
//using (SMTPServer handler = new SMTPServer(listener.AcceptTcpClient()))
while (true)
{
SMTPServer handler = new SMTPServer(listener.AcceptTcpClient());
Thread thread = new System.Threading.Thread(new ThreadStart(handler.Run));
thread.Start();
}
}
public void Run()
{
string sadress;
string radress;
string rserver;
bool auth = false;
writer.WriteLine("220 smtp.localsmtp.de ESMTP server ready");
for (string line = reader.ReadLine(); line != null; line = reader.ReadLine())
{
Console.Error.WriteLine("Read line {0}", line);
if (line.StartsWith("EHLO"))
{
writer.WriteLine("250-smtp.localsmtp.de");
//Auth ankuendigen
writer.WriteLine("250 AUTH PLAIN");
}
if (line.StartsWith("QUIT"))
{
writer.WriteLine("221 Bye Sweetie see ya");
client.Close();
}
#region auth
if (line.StartsWith("AUTH PLAIN"))
{
Console.WriteLine("client sendet Auth: " + line);
string [] pw = line.Split(new string[] { "PLAIN " }, StringSplitOptions.None);
byte[] bytes = Convert.FromBase64String(pw[1]);
string result = Encoding.BigEndianUnicode.GetString(bytes);
if (result == "12")
{
writer.WriteLine("235 2.7.0 Authentication successful");
auth = true;
}
else
{
Console.WriteLine("Falsche AUTH Daten");
writer.WriteLine("535 – Incorrect authentication data");
}
}
#endregion
#region sender
if (line.StartsWith("MAIL FROM") && auth == true)
{
string[] sadressa = line.Split(new string[] { "FROM:" }, StringSplitOptions.None);
sadress = sadressa[1];
//Absender
sadress = sadress.Replace("<","").Replace(">","");
//Debug
Console.WriteLine("Absender: " + sadress);
writer.WriteLine("250 OK");
}
#endregion
#region receiver
if (line.StartsWith("RCPT TO:") && auth == true)
{
string[] radressa = line.Split(new string[] { "RCPT TO:" }, StringSplitOptions.None);
radress = radressa[1];
//Empfänger
radress = radress.Replace("<", "").Replace(">", "");
if (samplesmtp.getMX.GetMXRecord(radress) != "invalid")
{
rserver = samplesmtp.getMX.GetMXRecord(radress);
Console.WriteLine("MX Record: " + rserver);
}
else
Console.WriteLine("ALARM");
//Debug
Console.WriteLine("Empfänger: " + radress);
writer.WriteLine("250 OK");
}
#endregion
#region data
if (line.StartsWith("DATA") && auth == true)
{
writer.WriteLine("354 start mail input");
var emailLine = reader.ReadLine();
while (!emailLine.Equals("."))
{
// add emailLine to the email body
string[] emailbody = new string[] {emailLine};
Console.WriteLine("Emailbody: " + emailbody[0]);
}
reader.Close();
writer.Close();
stream.Dispose();
writer.WriteLine("250 OK");
}
#endregion
}
}
}
}
Trying to call .Flush() manually in code doesn't change the problem at all. No effect.
In answer to your actual question you want to read all the lines until you receive a . on a line on it's own (see https://www.ietf.org/rfc/rfc2821.txt), something like this: -
var emailLine = reader.ReadLine();
while (!emailLine.Equals("."))
{
// add emailLine to the email body
emailLine = reader.readLine();
}
writer.WriteLine("250 OK");
reader.Close();
writer.Close();
stream.Dispose();
In response to your comment to mine:
public class SMTPServer : IDisposable
{
// all the other stuff
public void Dispose()
{
writer.Dispose();
reader.Dispose();
stream.Dispose();
}
}
calling code:
static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Loopback, 25);
listener.Start();
using (SMTPServer handler = new SMTPServer(listener.AcceptTcpClient()))
{
while (true)
{
Thread thread = new System.Threading.Thread(new ThreadStart(handler.Run));
thread.Start();
}
}
}

Categories

Resources