Send a general EMail with Messaging Module

Topics: Customizing Orchard, Writing modules
May 15, 2011 at 5:36 PM
Edited May 15, 2011 at 5:40 PM

I want to use the EMail Messaging module to send a general message that is simply typed into a form on my Module with a recipient, subject and body. The MessageManager however requires a ContentItemRecord as a first parameter. I do not have a content item in this senario so I thought i would pass a null parameter value and include all other vlaues in the properties parameter where I can assign the neccessary in the IMessageEventHandler including the To address of the context object as it seems the ContentItemRecord is used for assigning the to address. The User Module MessageEventHandler however blows up as the MessageContext Recipient object is null. Anybody have an idea as to how this issue can be circumvented or sending message without ContentItemRecord can be achieved.

May 16, 2011 at 12:29 PM

I think it expects you to pass in a User object, which is actually just another content type in Orchard. You could maybe create a dummy user, or maybe a separate content type with userpart, to represent the recipient.

May 16, 2011 at 12:57 PM

Thanks, I just think that is a very convoluted way for a very simple function like sending email. Not sure why the developer of the EMail Messaging functionality created such a dependency. I will strip out the code and just use the SMTP settings stored and do my own Email sending in my module. 

May 19, 2011 at 8:00 AM
Edited May 19, 2011 at 8:48 AM

Some feedback for others who are interested to do the same as I did with sending email without any record reference from that database:

In your controller call the Send method with a new ContentItemRecord() parameter. This will effectively return a 0 Id in all the areas where the record is retrieved causing those handlers to be ignored unless somewhere in the database there is a 0 id record (Would only probably be if someone has hacked the database).  Then pass all your parameters including the to address.

[HttpPost, ActionName("SendEMail")]
public ActionResult SendEMailPOST(string to, string cc, string bcc, string subject, string body)
{
	body = System.Web.HttpUtility.HtmlDecode(body);
	_messenger.Send(new ContentItemRecord(), MessageTypes.SendEMail, "email", 
	new Dictionary<string, string> { 
		{ "To", to }, 
		{ "CC", cc }, 
		{ "Bcc", bcc }, 
		{ "Subject", subject }, 
		{ "Body", body } 
	});
	return View("Window/Close");
}
In your module's MessageEventHandler exclude the code that checks for the Recipient and assign the recipient
directly through the context.MailMessage property as demonstrated below.

public void Sending(MessageContext context)
{
	if (context.MessagePrepared)
		return;

	//var contentItem = _contentManager.Get(context.Recipient.Id);
	//if (contentItem == null)
	//  return;

	//var recipient = contentItem.As<UserPart>();
	//if (recipient == null)
	//  return;

	switch (context.Type)
	{
		case MessageTypes.SendEMail:
			context.MailMessage.To.Add(context.Properties["To"]); //TODO: if delimited list step through all and add individually;
			if (!string.IsNullOrWhiteSpace(context.Properties["CC"])) { context.MailMessage.CC.Add(context.Properties["CC"]); }
			if (!string.IsNullOrWhiteSpace(context.Properties["Bcc"])) { context.MailMessage.Bcc.Add(context.Properties["Bcc"]); }
			context.MailMessage.Subject = context.Properties["Subject"];
			context.MailMessage.IsBodyHtml = true;
			context.MailMessage.Body = context.Properties["Body"];
			context.MessagePrepared = true;
			break;
		}
	}
}
 
A possible caveat could be if someone creates a module and does testing without proper error handling against a possible null
object through the context ContentItemRecord.
Dec 29, 2013 at 9:37 PM
I'm running into two issues here:
1) MessageTypes.SendEMail is coming back as undefined. MessageTypes belongs to Orchard.Users.Models. There doesn't appear to anything related to Orchard.Email or Orchard.Messaging that defines SendEmail. So I'm using MessageTypes.Validation instead. Which may be related to the next issue.
2) I have implemented IMessageEventHandler and instantiated Sending() & Sent(). But when I execute the code above, while messages are sent out, none of the data I've included is included. The recipients get the emails. But nothing else is included.

Given that this thread is over 2 1/2 years old, I'm highly suspicious that this particular model has been deprecated. If so, then how do I do the above now? I've been googling around, and this is all I've really been able to find. Any help would be highly appreciated.
Developer
Dec 29, 2013 at 10:02 PM
  1. The MessageType is a user defined value. When you implement your own message handler, you need to check against the message type you passed in when invoking IMessageManager.Send.
  2. Although this messaging API is going to be deprecated in favor of a newer API, it does work. If you provide us with code we may be able to see why it isn't working. What data are you passing through from where exactly?
Dec 30, 2013 at 4:19 PM
sfmskywalker wrote:
  1. The MessageType is a user defined value. When you implement your own message handler, you need to check against the message type you passed in when invoking IMessageManager.Send.
  2. Although this messaging API is going to be deprecated in favor of a newer API, it does work. If you provide us with code we may be able to see why it isn't working. What data are you passing through from where exactly?
K. I figured out what was wrong, but it was kind of weird. I was getting an exception with this:
    if (!string.IsNullOrWhiteSpace(context.Properties["Bcc"])) {
        context.MailMessage.Bcc.Add(context.Properties["Bcc"]); 
    }
The odd thing about it was that no exception was actually being picked up in VS until I put a break in following that line. It was occurring with the first "context.Properties["Bcc"]".

Once I handled it properly, everything worked fine. Not sure why VS wasn't handling the exception properly, but ... whatever.

One other question: Is it possible to override the "From" field? I see that it comes from the Email settings. I tried to override it with:
    if (!string.IsNullOrWhiteSpace(context.Properties["From"])) {
        context.MailMessage.From = new MailAddress(context.Properties["From"]);
    }
But that was basically ignored. It'd be nice if there is a way to customize that field, as I have different messages that I want to send from different "sources".
Developer
Dec 30, 2013 at 4:29 PM
Edited Dec 30, 2013 at 4:31 PM
You can configure Visual Studio to break on exceptions when they are thrown (Debug -> Exceptions -> Common Language Runtime Exceptions -> check Thrown).
Unfortunately you can't currently override the "From" field. What you can do instead:

a) Change the value of the SmtpSettingsPart on the fly, or
b) Implement your own IMessagingChannel implementation and take full control, or
c) Change the current implementation of EmailMessagingChannel to only set the From property if it is not already set.

Both a) and c) aren't ideal obviously, so I'd probably go with b) and maybe create a pull request for c).