Thursday, July 3, 2008

SPUtility.SendEmail

I want to make one comment about this method. It cannot be used out of a SharePoint context because inside it uses SPControl.GetContextWeb(HttpContext.CurrentIL. I wanted to use it to send an email from a timer job.

Have you any idea to send an email using the web applications settings for the outgoing mail from a timer job?

9 comments:

Anonymous said...

Hi Álex

I haven't tried this but one option could be to implement a small Custom SharePoint Web Service which calls SPUtility.SendEmail for you and then call that on the rootweb of the first site in the WebApplication

Anonymous said...

Why not use the regular .NET mail thingies?

Setup a local SMTP server which forwards the mail to your regular mail server.

Victor

Anonymous said...

You can create a SPWeb object in your code:
SPSite site = new SPSite(ADDRESS_OF_SITE_JOB_INSTALLED_ON);
SPWeb web = site.OpenWeb();
StringDictionary headers = new StringDictionary();
headers.Add("to", email);
headers.Add("from", from);
headers.Add("subject", subject);
foreach (DataRowView row in DataSource)
SPUtility.SendEmail(web, headers, GetMailBody(bodyFormat, row));

Sorry for my English :)

Àlex said...

Wow,
This post is hot ;)

Get the SPWeb from the SPSite url will not work (the SendMail accepts an SPWeb object as a parameter, but it uses it to get the current user). The problem is that inside SPUtility.SendEmail it attempts to get the SPWeb object from the current HttpContext and it does not uses the SPWeb passed(I have seen it using the Reflector), and I have not any HttpContext because it executes from a timer job.

The other options involves developing or installing other components (WS or local SMTP server) and I have discarded by the moment.

Finally I have sent the email using the System.Net.Mail classes and sending to the server configured in the Central Administration (getting the server from the SPWeb properties).

This solution is portable to other farm and it is not necessary to add anything to the farm.

PaulE said...
This comment has been removed by the author.
PaulE said...

Hi Álex,

Thanks for pointing out the Context problem. I looked closer at the disassembly with Reflector and it appears there are two "flavors" of SPUtility.SendEmail. The version which uses StringDictionary correctly uses the SPWeb object given to it IF HttpContext.Current returns null. The version where you supply the partial header info in the method invocation uses Microsoft.SharePoint.MailMessage which, although it has the SPWeb object, never uses the given SPWeb object in the sending method (MailMessage.FSend()).

So, in short, try the SPUtility.SendEmail methods which take a StringDictionary. I have successfully used them from a timer job.

Anonymous said...

There is a Microsoft post about this.

http://support.microsoft.com/kb/948321/en-us

To get the current web, you can use the following code (from the above article), that gets the site and web from the AlertHandler properties.

public bool OnNotification(SPAlertHandlerParams ahp)
{
SPSite site = null;
SPWeb web = null;

try
{
site = new SPSite(ahp.siteUrl+ahp.webUrl);
web = site.OpenWeb();

vedanshu said...

Try the code present within this link to create a new HttpContext instance and then assign it to the SPWeb

http://stsadm.blogspot.com/2008/12/ensuring-valid-spcontext-via-feature.html

Thanks
Vedanshu

Whut said...

There is a way!

SmtpClient smtp = new SmtpClient(this.WebApplication.OutboundMailServiceInstance.Server.Address);

smtp.UseDefaultCredentials = (smtp.Credentials == null);

smtp.Send(mailMessage);

Found here:
http://www.codeproject.com/KB/sharepoint/SPScheduedReminders.aspx

 
Online Visitors