Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Open default mail client along with a attachment

Tags:

c#

email

wpf

Hi I am working on a WPF application (using c#).

I need to have a functionality where users can send files (audio files) as attachments via email. I tried using Microsoft.Office.Interop.Outlook.Application namespace but it opens outlook and wont work if outlook is not installed on the client's computer.

I tried using SmtpClient() and MailMessage() classes of System.Net.Mail namespace but its not opening email client. Its sending a mail through predefined server (might be a problem since I don't know what my client's default email domain is. This link has all the things I need and its working fine.

But there they used DllImport attribute and there are many issues that may arise (from what I can understand) from using this method. I have no idea about managed and un-managed code so I am not able to understand what the problem is. Is it OK to follow the example in the above link. If not why?

Can you tell or provide links on how to approach my problem

like image 565
Raj123 Avatar asked Dec 02 '13 12:12

Raj123


People also ask

Where is the default mail client setting in Outlook?

Open Outlook. On the Tools menu, click Options, and then click the Other tab. Under General, select the Make Outlook the default program for E-mail, Contacts, and Calendar check box. Click OK.

What is a default email client?

The default mail program is the software that is registered with your operating system as the software that is to handle mailto URL's. When another application wants to send an email, it looks up the default and passes the email to the default mail program.


2 Answers

We can make use of the fact that most email clients support the .EML file format to be loaded.

So if we Extend the System.Net.Mail.MailMessage Class in a way that it can be saved to the filesystem as an .EML file. The resulting file can be opened with the default mail client using Process.Start(filename)

For this to work properly we have to add a line containing "X-Unsent: 1" to the .EML file. This line tells the email client loading the .EML file the message must be presented in "New message" mode.

Use the "addUnsentHeader" bool parameter of the extension method to add this line to the .EML file

The extension method looks like this:

using System; using System.IO; using System.Net.Mail; using System.Reflection;  namespace Fsolutions.Fbase.Common.Mail {     public static class MailUtility     {         //Extension method for MailMessage to save to a file on disk         public static void Save(this MailMessage message, string filename, bool addUnsentHeader = true)         {             using (var filestream = File.Open(filename, FileMode.Create))             {                 if (addUnsentHeader)                 {                     var binaryWriter = new BinaryWriter(filestream);                     //Write the Unsent header to the file so the mail client knows this mail must be presented in "New message" mode                     binaryWriter.Write(System.Text.Encoding.UTF8.GetBytes("X-Unsent: 1" + Environment.NewLine));                 }                  var assembly = typeof(SmtpClient).Assembly;                 var mailWriterType = assembly.GetType("System.Net.Mail.MailWriter");                  // Get reflection info for MailWriter contructor                 var mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null);                  // Construct MailWriter object with our FileStream                 var mailWriter = mailWriterContructor.Invoke(new object[] { filestream });                  // Get reflection info for Send() method on MailMessage                 var sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic);                  sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { mailWriter, true, true }, null);                  // Finally get reflection info for Close() method on our MailWriter                 var closeMethod = mailWriter.GetType().GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic);                  // Call close method                 closeMethod.Invoke(mailWriter, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { }, null);             }         }     } } 

Use the extension method like this:

        var mailMessage = new MailMessage();         mailMessage.From = new MailAddress("[email protected]");         mailMessage.Subject = "Your subject here";         mailMessage.IsBodyHtml = true;         mailMessage.Body = "<span style='font-size: 12pt; color: red;'>My HTML formatted body</span>";          mailMessage.Attachments.Add(new Attachment("C://Myfile.pdf"));          var filename = "C://Temp/mymessage.eml";          //save the MailMessage to the filesystem         mailMessage.Save(filename);          //Open the file with the default associated application registered on the local machine         Process.Start(filename); 
like image 145
Williwyg Avatar answered Oct 06 '22 00:10

Williwyg


Have you tried using System.Diagnostics.Process.Start() with an appropriate command line?

mailto:[email protected]?subject=an email&body=see attachment&attachment="/files/audio/attachment.mp3" 

The &attachment switch lets you specify a file name.

Ok, I'm struggling to this working but allegedly it can be done. I'm currently reading through this monster and will get back to you.

like image 36
Gusdor Avatar answered Oct 06 '22 00:10

Gusdor