If you’re developing an email send action, or using the default send-email action in WFFM, you probably want to test it out before you send it to the world. If you’re working locally, then a great idea is to use SMTP4Dev to test things out. This allows you to see the email in context by listening for emails to come across a certain port (default is 25).
What if you want to do this on a remote server? You won’t likely be logged in, so you can’t actually see what the email is looking like. But, there is a way! Out of the box, WFFM uses a pipeline for sending emails. These pipelines do a couple things: Expand the Tokens, set attachments, Expand Links, and a few others. This all occurs in the processMessage pipeline below:
<processMessage patch:source="Sitecore.Forms.config"> <processor type="Sitecore.Forms.Core.Pipelines.ProcessMessage, Sitecore.Forms.Core" method="ExpandLinks"/> <processor type="Sitecore.Forms.Core.Pipelines.ProcessMessage, Sitecore.Forms.Core" method="ExpandTokens"> <ItemRepository ref="/sitecore/wffm/itemRepository"/> <FieldProvider ref="/sitecore/wffm/fieldProvider"/> </processor> <processor type="Sitecore.Forms.Core.Pipelines.ProcessMessage, Sitecore.Forms.Core" method="AddHostToItemLink"/> <processor type="Sitecore.Forms.Core.Pipelines.ProcessMessage, Sitecore.Forms.Core" method="AddHostToMediaItem"/> <processor type="Sitecore.Forms.Core.Pipelines.ProcessMessage, Sitecore.Forms.Core" method="AddAttachments"> <ItemRepository ref="/sitecore/wffm/itemRepository"/> </processor> <processor type="Sitecore.Forms.Core.Pipelines.ProcessMessage, Sitecore.Forms.Core" method="BuildToFromRecipient"/> <processor type="Sitecore.Forms.Core.Pipelines.ProcessMessage, Sitecore.Forms.Core" method="SendEmail"/> </processMessage>
Looking at the highlighted line above, you can see the final step in the process is to send the email. What if we replaced that with a debug processor? I like XML for this, since it can organize data into a way that is easy to visually diagnose. Check out this processor:
using System; using System.IO; using System.Text; using System.Xml; using Sitecore.WFFM.Abstractions.Mail; namespace Client.Framework.Forms.Pipelines { public class DebugSendEmail { public void LogEmail(ProcessMessageArgs args) { var tempFolder = Path.Combine(Sitecore.Configuration.Settings.TempFolderPath, "MailLog"); if (!Directory.Exists(tempFolder)) Directory.CreateDirectory(tempFolder); var fullPath = Path.Combine(tempFolder, DateTime.Now.ToFileTimeUtc() + ".xml"); using (var writer = XmlWriter.Create(fullPath)) { writer.WriteStartDocument(); writer.WriteStartElement("MailMessage"); writer.WriteAttributeString("IsBodyHtml", args.IsBodyHtml.ToString()); writer.WriteAttributeString("Host", args.Host); writer.WriteAttributeString("Port", args.Port.ToString()); // From writer.WriteStartElement("From"); writer.WriteRaw(args.From); writer.WriteEndElement(); // To writer.WriteStartElement("To"); writer.WriteRaw(args.To.ToString()); writer.WriteEndElement(); // CC if (args.CC != null && args.CC.Length > 0) { writer.WriteStartElement("CC"); writer.WriteCData(args.CC.ToString()); writer.WriteEndElement(); } // Bcc if (args.BCC != null && args.BCC.Length > 0) { writer.WriteStartElement("Bcc"); writer.WriteCData(args.BCC.ToString()); writer.WriteEndElement(); } // Subject writer.WriteStartElement("Subject"); writer.WriteCData(args.Subject.ToString()); writer.WriteEndElement(); // Body writer.WriteStartElement("Body"); writer.WriteCData(args.Mail.ToString()); writer.WriteEndElement(); writer.WriteEndElement(); //MailMessage writer.WriteEndDocument(); } } } }
That looks like a bunch of code, doesn’t it? It’s not too bad. First we’re going to snag the Temp Folder from Sitecore. Then we’ll drop in a MailLog folder to organize things. After that, we just write the attributes of the email to the XML and we’re done. We patch this in via a simple config below:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> <sitecore> <pipelines> <processMessage> <processor type="Client.Framework.Forms.Pipelines.DebugSendEmail, Client.Framework" method="SendEmail" patch:instead="processor[@type='Sitecore.Forms.Core.Pipelines.ProcessMessage, Sitecore.Forms.Core' and @method='SendEmail']" /> </processMessage> </pipelines> </sitecore> </configuration>
Btw, I gave myself a gold start for the boolean expression in the patch:instead. I’d not had to do that before and wasn’t 100% sure it would work. It did though!
If you have any issues with this code, let me know in the comments below.