How can I save an email instead of sending when using SmtpClient?

C#.NetEmailSmtp

C# Problem Overview


I am using SmtpClient to send an email with an attachment. However for a certain batch we need to somehow save the MailMessage instead of sending them. We are then thinking/hoping to manually upload the messages to the users drafts folder.

Is it possible to save these messages with the attachment intact (impossible, I would have thought). Or alternatively upload the messages to a folder in the users account?

If anyone has any experience of this, I'd much appreciate a bit of help or a pointer.

C# Solutions


Solution 1 - C#

When testing in ASP.NET we save our emails to a folder rather then send them through an email server. Maybe you could change yourweb.config settings like this for your batch?

<system.net>
  <mailSettings>
    <smtp deliveryMethod="SpecifiedPickupDirectory">
      <specifiedPickupDirectory pickupDirectoryLocation="c:\Temp\mail\"/>
    </smtp>
  </mailSettings>
</system.net>

Additional Info:

Solution 2 - C#

As well as the SpecifiedPickupDirectory information of the other answers, if you want to ensure your emails are sent to a folder relative to the site root - handy in testing on build servers where you don't know the paths - you can add a quick check in your email sending code:

	SmtpClient client = new SmtpClient();
	...

	// Add "~" support for pickupdirectories.
	if (client.DeliveryMethod == SmtpDeliveryMethod.SpecifiedPickupDirectory && client.PickupDirectoryLocation.StartsWith("~"))
	{
		string root = AppDomain.CurrentDomain.BaseDirectory;
		string pickupRoot = client.PickupDirectoryLocation.Replace("~/", root);
		pickupRoot = pickupRoot.Replace("/",@"\");
		client.PickupDirectoryLocation = pickupRoot;
	}

And your tests will look something like this (make sure you use App_Data so IIS can write to the folder):

	// Arrange - get SitePath from AppDomain.Current.BaseDirectory + ..\
	string pickupPath = Path.Combine(SitePath, "App_Data", "TempSmtp");
	if (!Directory.Exists(pickupPath))
		Directory.CreateDirectory(pickupPath);

	foreach (string file in Directory.GetFiles(pickupPath, "*.eml"))
	{
		File.Delete(file);
	}

	// Act (send some emails)

	// Assert
	Assert.That(Directory.GetFiles(pickupPath, "*.eml").Count(), Is.EqualTo(1));

Solution 3 - C#

This can help - Adding Save() functionality to Microsoft.Net.Mail.MailMessage
The main ideia, make an extension to MailMessage ,that by reflection making a save method.

Solution 4 - C#

You can configure this with the system.net setting in your web.config / app.config file.

<system.net>
  <mailSettings>
    <smtp deliveryMethod="Network">
      <network host="mail.mydomain.com" port="25" />
    </smtp>
    <!-- Use this setting for development
    <smtp deliveryMethod="SpecifiedPickupDirectory">
      <specifiedPickupDirectory pickupDirectoryLocation="C:\Temp" />
    </smtp>
    -->
  </mailSettings>
</system.net>

Also, here's a link with info on migrating from System.Web.Mail to System.Net.Mail.

Solution 5 - C#

A bug also requires adding as a workaround in some versions of the framework. So the completed version looks like:

<system.net>
  <mailSettings>
	<smtp deliveryMethod="SpecifiedPickupDirectory">
		<specifiedPickupDirectory pickupDirectoryLocation="c:\Temp\mail\"/>
        <network host="localhost" />
	</smtp>
  </mailSettings>
</system.net>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser17510View Question on Stackoverflow
Solution 1 - C#LeahView Answer on Stackoverflow
Solution 2 - C#Chris SView Answer on Stackoverflow
Solution 3 - C#AvramView Answer on Stackoverflow
Solution 4 - C#dotjoeView Answer on Stackoverflow
Solution 5 - C#devjinView Answer on Stackoverflow