How to save MailMessage object to disk as *.eml or *.msg file
For simplicity, I'll just quote an explanation from a Connect item:
You can actually configure the
SmtpClient to send emails to the file
system instead of the network. You can
do this programmatically using the
following code:SmtpClient client = new SmtpClient("mysmtphost");
client.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
client.PickupDirectoryLocation = @"C:\somedirectory";
client.Send(message);
You can also set this up in your
application configuration file like
this:
<configuration>
<system.net>
<mailSettings>
<smtp deliveryMethod="SpecifiedPickupDirectory">
<specifiedPickupDirectory pickupDirectoryLocation="C:\somedirectory" />
</smtp>
</mailSettings>
</system.net>
</configuration>
After sending the email, you should
see email files get added to the
directory you specified. You can then
have a separate process send out the
email messages in batch mode.
You should be able to use the empty constructor instead of the one listed, as it won't be sending it anyway.
How to save MailMesage to .msg file?
How exactly are you creating the MSG file? It is completely different from an EML file - see https://stackoverflow.com/questions/16229591/difference-between-a-msg-file-and-a-eml-file/16230261#16230261
MSG file format is a binary IStorage
file, and its format is documented. You can parse your EML (MIME) file and copy one property at a time to a programmatically created MSG file.
If using Redemption is an option (I am its author), you can use Session.CreateMessageFromMsgFile to create a new MSG file and RDOMail.Import
method to import your existing EML file.
set Session = CreateObject("Redemption.RDOSession")
set Msg = Session.CreateMessageFromMsgFile("c:\temp\test.msg")
Msg.Sent = true '//since Import does not copy this property
Msg.Import("c:\temp\test.eml", 1024) ' //1024 is olRfc822
Msg.Save
Save Email as .eml with original email.body
You are essentially reassembling the message from a few properties. Why not grab the whole MIME message (with all the headers, attachments etc.)?
See https://docs.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-export-items-by-using-ews-in-exchange
How to save System.Net.Mail MailMessage object into SQL Server database?
I think the update you posted is pretty good. Also check out this answer for How to save MailMessage object to disk as *.eml or *.msg file. You probably can create multiple clients, one to properly send and other to save the message to local file, which then needs to be saved to DB. I haven't tried this though.
If you are still looking into this, posted sample code...
Restricted to single attachment only. The sample is only to get you started and should not be taken as is. There is a lot of room for improvements.
We load the attachment into a byte[]
and then add it as a Attachment(Stream s)
. We save this into the db as our VARBINARY
content.
Your First send method, that also saves the message to db
try
{
MailMessage message = new MailMessage();
var logoPath = @"C:\MyLogo.jpg";
message.From = new MailAddress("from@email.co.nz");
message.To.Add("to@email.co.nz");
message.IsBodyHtml = true;
//Read the attachment into byte Array. This assumes single attachment only in the Mail Message.
byte[] arr = File.ReadAllBytes(logoPath);
using (var stream = new MemoryStream(arr))
{
stream.Position = 0;
Attachment logo = new Attachment(stream, "Logo");
string contentID = "Image";
logo.ContentId = contentID;
logo.ContentDisposition.Inline = true;
logo.ContentDisposition.DispositionType = DispositionTypeNames.Inline;
string wsHdr = "<html><body><p><a href=\"http://www.tecnq.com.au\" target=\"_blank\"><img alt=\"tecnqlogo\" src=\"cid:" + contentID + "\" style=\"border-style:none; height:34px; width:100px\" /></a></p>" + "</html></body>"; ;
message.Body = wsHdr;
message.Attachments.Add(logo);
SmtpClient smtp = new SmtpClient();
smtp.Host = "MyServer";
smtp.Port = 25;
smtp.Send(message);
SaveMessage(message, arr);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
To Save the mail message
//ZERO ERRO CHECKING.
private static void SaveMessage(MailMessage message, byte[] arr)
{
using (var conn = new SqlConnection("CONNECTION_STRING"))
{
using (var cmd = new SqlCommand("INSERT INTO MailSent (Body,Attachment) VALUES(@BODY,@ATTACHMENT)", conn))
{
conn.Open();
var param = new SqlParameter("@BODY", SqlDbType.VarChar)
{
Value = message.Body
};
var param2 = new SqlParameter("@ATTACHMENT", SqlDbType.Binary)
{
Value = arr
};
cmd.Parameters.Add(param);
cmd.Parameters.Add(param2);
cmd.ExecuteNonQuery();
}
}
}
Resend message
try
{
MailMessage message = new MailMessage();
byte[] arr2 = null;
GetMailMessage(2, ref message, ref arr2);
message.From = new MailAddress("from@email.co.nz");
message.To.Add("to@email.co.nz");
message.IsBodyHtml = true;
using (var stream = new MemoryStream(arr2))
{
stream.Position = 0;
Attachment logo = new Attachment(stream, "Logo");
string contentID = "Image";
logo.ContentId = contentID;
logo.ContentDisposition.Inline = true;
logo.ContentDisposition.DispositionType = DispositionTypeNames.Inline;
message.Attachments.Add(logo);
SmtpClient smtp = new SmtpClient();
smtp.Host = "MyServer";
smtp.Port = 25;
smtp.Send(message);
}
// SaveMessage(message, arr);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
To Retrieve the message
//ZERO ERROR CHECKING.
private static void GetMailMessage(int itemId, ref MailMessage msg2, ref byte[] arr2)
{
using (var conn = new SqlConnection("CONNECTION_STRING"))
{
using (var cmd = new SqlCommand("SELECT [Body],[Attachment] FROM MailSent WHERE ID = @itemId", conn))
{
conn.Open();
cmd.Parameters.AddWithValue("@itemId", itemId);
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
msg2.Body = dr[0].ToString();
arr2 = dr[1] as byte[];
}
}
}
}
}
Create eml file in memory without saving it on disk
Look into using MimeKit.
You can write the MimeMessage objects to any type of stream that you want, including a MemoryStream.
Specify .eml file name using System.Net.Mail.MailAddress or other library
Allan Eagle over at CodeProject.com has created an extension of the System.Net.Mail.MailMessage class that includes the ability to save an email with a specific file name. I believe this will address the issue you raised.
Related Topics
How to Generate Getters and Setters in Visual Studio
How to Set Datetimepicker to Month and Year Only Format
C# Linq Using Null or Empty Strings in a Where Statment
Merge Multiple Lists into One List With Linq
Remove Hours:Seconds:Milliseconds in Datetime Object
C# Check the Empty or Null Value in All Datatable Values
Newtonsoft.Json Serializeobject Without Escape Backslashes
Sending Array of Bytes from Client to Server
How to Write Data to a Text File Without Overwriting the Current Data
Asp.Net Core Identity Successful Login Redirecting Back to Login Page
Asp.Net Web Api:Correct Way to Return a 401/Unauthorised Response
Convert Byte Array to Wav File
How to Call a Method Daily, At Specific Time, in C#
How to Store List of Data from Database to Arraylist or List in C#
Converting Datetime C# Type to Date JavaScript in ASP.NET MVC Razor Application
Using C# Lambda to Split String and Search Value