I'm trying to use Timer Jobs as part of a system to send out special periodic emails to users of our SharePoint site collections. The timer jobs work... except when it comes to actually sending the emails.
They can perform any other task as if they are the System Account, including creating and modifying list items. But when I try to send an email with it, I get the following error and stacktrace:
Mailbox unavailable. The server response was: 5.7.1 Client does not have permissions to send as this sender
at System.Net.Mail.MailCommand.CheckResponse(SmtpStatusCode statusCode, String response)
at System.Net.Mail.SmtpTransport.SendMail(MailAddress sender, MailAddressCollection recipients, String deliveryNotify, SmtpFailedRecipientException& exception)
at System.Net.Mail.SmtpClient.Send(MailMessage message)
Apart from the acquisition of the SPSite object (fetched from SPWebApplication.Sites), everything else of this routine is exactly the same as an email system I use within a workflow on the site collection (which uses SPWorkflowActivationProperties.Site). The same To, the same From (and thus the sender should be valid, which makes the error perplexing), and the same SMTP routine. We use System.Net.Mail to send the emails.
Below is the Execute(Guid) function of my Timer Job.
SPWebApplication oWebApp = this.Parent as SPWebApplication;
SPContentDatabase oConDB = oWebApp.ContentDatabases[targetInstanceId];
// Iterate through the site collections which the timer job is activated on
foreach (string str in oWebApp.Properties.Keys.OfType<string>().Where(k => k.EndsWith(key)))
{
using (SPWeb targetWeb = oConDB.Sites[oWebApp.Properties[str].ToString()].RootWeb)
{
SPList taskList = targetWeb.Lists["Tasks"];
// The actual code here uses a mediator class to build a System.Net.Mail.MailMessage with a valid recipient and sender.
// For the purposes of this question, I've expanded the code's class to show what happens on the System.Net.Mail level rather than through the mediator.
System.Net.Mail.MailMessage message = System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
message.From = "sharepoint@company.com";
message.To.Add("tester@company.com");
message.Subject = "TIMER ALERT JOB";
message.Body = "If you receive this email, the Timer Job is working and you can start working on all that meaty, complex listitem-based do-everything system!"
message.IsBodyHtml = true;
System.Net.Mail.SmtpClient smtpClient = new System.Net.Mail.SmtpClient(oWebApp.OutboundMailServiceInstance.Server.Address);
smtpClient.UseDefaultCredentials = true;
try { smtpClient.Send(message); }
finally { smtpClient = null; message.Dispose(); }
}
}
Now, as mentioned above, the only difference in the code between the Timer Job above and the workflow version is how the SPSite object is fetched. Yet, only the Timer Job version will throw the error. Is there something else needed for sending email with a Timer Job, is there something I am missing? Is it as simple a matter as SPSecurity.RunWithElevatedPrivileges? The fact it works on the workflow (as well as anywhere else, this mail system is also used in some ASPX pages and Event Handlers without error) but not in the Timer Job leads me to believe there's something specific about Timer Jobs rather than it being a system configuration. Or, at least, that something about the Timer Job makes it different enough from the workflows and everything else to make the server configuration consider it invalid...
