I would like to send an email from within sharepoint to a user on the local domain, after an event reciever has been triggered.
How would I go about this?
Any help would be much appreciated.
Many Thanks,
Freddie
You didn't really gave much context to your question, so I'm just going to point out the simplest alternative.
In most situations, you should be just be able to use one of the SPUtility.SendMail(..) overloads
So, something like this should be sufficient
var headers = new StringDictionary();
headers.Add("from", from);
headers.Add("to", to);
headers.Add("cc", cc);
headers.Add("bcc", bcc);
headers.Add("subject", subject);
headers.Add("content-type", "text/html");
SPUtility.SendEmail(web, headers, body);
That said, keep in mind that SPUtility.SendEmail isn't very robust (sometimes, it won't even point out if an error occurred while sending the mail...).
For this reason, some sources prefer to just use the well documented SmtpClient instead. In that case, the only problematic part is getting the outbound email server address.
SmtpClient client = new SmtpClient();
client.Host = currentWeb.Site.WebApplication.OutboundMailServiceInstance.Server.Address;
As you can see, one possible option is getting it from the web application associated to the current web site (that is, assuming you have a valid SPContext at the time and are therefore able to access the current web site in the first place). From here, just build the MailMessage instance and send it using client.Send(message);.
Related
I've been trying to find an answer to this within MSDN documentation and various other resources, but am unable to find something that works.
Here is some C# code I am using:
private ExtendedPropertyDefinition SurpressAutoResponse = new ExtendedPropertyDefinition(
DefaultExtendedPropertySet.InternetHeaders,
"X-Auto-Response-Suppress",
MapiPropertyType.String); // Also tried with StringArray and Integer
private ExtendedPropertyDefinition OtherID = new ExtendedPropertyDefinition(
DefaultExtendedPropertySet.InternetHeaders,
"X-Custom-ID-Property-Example",
MapiPropertyType.String);
{ some other code that's unimportant in between }
var mm = new EmailMessage(Global.Exchange);
mm.ToRecipients.Add("me#me.com"); // example address, of course
mm.Subject = Subject.Replace('\r', ' ').Replace('\n', ' ');
mm.SetExtendedProperty(SurpressAutoResponse, "OOF, NDR"); // Also tried {"OOF", "NDR"} and -1
mm.SetExtendedProperty(OtherId, "12345-1");
mm.Body = "Hello World";
mm.Send();
When I inspect the headers for the incoming email, I see that my "OtherId" is correctly set, but the X-Auto-Response-Suppress is not set. Any ideas how I should be getting exchange to suppress these out of office and delivery failure reports?
Notes:
I am targeting an Exchange 2010_SP2 server, which should support this
References:
https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxcmail/ced68690-498a-4567-9d14-5c01f974d8b1
https://learn.microsoft.com/en-us/previous-versions/office/developer/exchange-server-2010/dd633654(v=exchg.80)
UPDATE
I decided to try testing the behavior of the email and set an auto-reply/OOF on my email account. Even though the properties of the email do not include the X-Auto-Response-Suppress header, I noticed that it indeed prevented a reply. My presumption is that the header is read on the Exchange server, which also probably processes the auto-responses instead of the client. Since the client doesn't act upon the header itself, Exchange saves some data by removing it from the original email before it's transferred. Can anyone who knows please confirm this is correct?
I have had issues using that header before as the MSDN is very vague on what all it actually does. And it is mostly only utilized by exchange servers and OOF purposes. Instead there are other headers that work better. Here is an article explaining why I think it would serve you well to use other headers. https://www.jitbit.com/maxblog/18-detecting-outlook-autoreplyout-of-office-emails-and-x-auto-response-suppress-header/
If you are only wanting to catch OOF then you can change the header to:
X-Auto-Response-Suppress:OOF
But I don't see that as a good example. Here is another thread on why this isn't always the best header to use: Detecting Outlook autoreply/out-of-office emails
We've seen a few similar questions on StackOverflow before regarding System.Web.Helpers.Webmail.Send but I see no proper explanation for what's going on.
Regarding the to: parameter, the documentation says:
The email address of the recipient or recipients. Separate multiple recipients using a semicolon (;).
and I've seen answers saying "use a comma because the docs are wrong", or "use a semicolon", or "maybe it's an environment issue".
The code
WebMail.Send(
to: "joe.bloggs#mail.com,jane.bloggs#mail.com",
from: "no-reply#company.com",
subject: "Some Automated Email",
body: "<strong>Lorem Ipsum</strong>",
isBodyHtml: true
);
I've tried a few scenarios:
joe.bloggs#mail.com;jane.bloggs#mail.com
No emails recieved: An invalid character was found in the mail header: ';'.
joe.bloggs#mail.com; jane.bloggs#mail.com
Only the first recipient receives the email
joe.bloggs#mail.com,jane.bloggs#mail.com
both recieved the email
joe.bloggs#mail.com, jane.bloggs#mail.com
both recieved the email
joe.bloggs#mail.com, non-existant#mail.com
First recieved the email, but uncaught exception: Mailbox unavailable. The server response was: 5.7.1 Unable to relay
non-existant#mail.com, joe.bloggs#mail.com
No emails recieved: An invalid character was found in the mail header: ','.
Can anybody shed some light on this? I've actually had even more bizzare behaviour on a different server; I'm using Exchange for the above tests, but actually experienced different behaviour on hMailServer where joe.bloggs#mail.com,jane.bloggs#mail.com resulted in a silent failure with no server errors and no outgoing mail in hMailServer logs. On the system with hMailServer I have only had success with a single address.
This probably has to do with the variety of relays you are connecting to, and the variety of methods they accept. Not only do the delimiter characters matter to each specific mail server, but the e-mail addresses also do (since different relays will be configure to accept certain e-mails, and will throw a variety of error codes back for bad e-mails, which will in turn throw a variety of exceptions).
The System.Net.Mail namespace has a MailMessage object that contains MailAddressCollection objects for To, CC, and Bcc that you can just call Add() on for each recipient.
I have a library that sends mail (without a relay) that uses it (everything goes to Bcc), you can check the code out there. If you happen to use the library, be sure to keep your IP address in good reputation and make sure your DNS records are all setup the same way you would if you were a relay (PTR and A records all setup).
As I understand it, the mistake in the documentation is the likely scenario. I don't have this assembly, so I can't confirm it in ILSpy, but apparently the helper class simply uses System.Net.Mail. Following the four parameter overload through I get to this internal method.
internal Message(string from, string to) : this()
{
//...
this.to = new MailAddressCollection
{
to
}
}
As a result, it simply creates a new MailAddressCollection which requires a comma delimiter. At no point did the to string ever replace or manipulate a semi-colon (unless this is done within the Helper class but that doesn't appear to be the case).
I know there are various thread out there related to this problem but i was unable to take any of the responses on those thread and make it work on my server.
So let try to see if someone can help me out here.
99% of the emails go out properly and few actually return with that error.
My code looks like this
MailMessage mm = new MailMessage(Settings.EmailCustomerService, to, subject, body);
mm.SubjectEncoding = Encoding.UTF8;
mm.BodyEncoding = Encoding.UTF8;
mm.IsBodyHtml = true;
MailAddress add = new MailAddress(Settings.EmailCustomerService, "Customer Service");
mm.From = add;
try
{
SmtpClient client = new SmtpClient(Settings.EmailSMTP);
client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential(Settings.EmailUser, Settings.EmailPwd);
System.Threading.ParameterizedThreadStart threadStart = new System.Threading.ParameterizedThreadStart(SendInThread);
threadStart.Invoke(new SendInThreadParams
{
client = client,
Message = mm
});
}
finally
{
mm = null;
}
Actually the Credentials code was added later but my code was run OK even without it. It just happen that 1% of the email never make it to the recipients and adding those 2 lines for Credentials did not make a difference.
The Settings.EmailUser is just a user on the server where the SMTP runs, but i have NOT attach it to nowhere.
I bet that's the problem.
The SMTP Server Relay is set to use 127.0.0.1 and the FQDN is just the name of the machine (something like "Machine1" ...nothing with a domain.com name)
The error I'm getting is this
Reporting-MTA: dns;Machine1
Received-From-MTA: dns;Machine1
Arrival-Date: Wed, 30 May 2012 23:08:36 -0700
Final-Recipient: rfc822;test#email.net
Action: failed
Status: 5.5.0
Diagnostic-Code: smtp;550 Access denied - Invalid HELO name (See RFC2821 4.1.1.1)
Return message emailed back was:
> This is an automatically generated Delivery Status Notification.
Delivery to the following recipients failed.
test#email.com
Thanks in advanced...
In addition to the message/delivery-status attachment, the DSN will usually have the returned message. For this sort of issue you should post the headers of the returned message and the DSN as well.
It looks to me like your server has accepted the message, but has an error transmitting it onwards. If your server had rejected it, your code would have thrown an exception. So your server Machine1 accepted it, attempted to transmit it to email.net, but email.net rejected it. Machine1 then generated a DSN (delivery status notification, in your case an NDR = Non-Delivery Report).
In other words it is a configuration error with the email server not a code problem. Almost certainly the issue is that the email server is not set up with an FQDN as you stated.
As a configuration problem, it belongs on ServerFault.
Based on BEN answer I realized that I was missing the PRIMARY DND SUFFIX.
Mainly in order to find out your FQDN, you need to simply:
1) Open a Command Prompt
2) Type "ipconfig /all"
Read your HOST NAME + PRIMARY DNS SUFFIX.
My DNS SUFFIX was emtpy so i went and added using this link
http://www.simpledns.com/kb.aspx?kbid=1227
And then rebooted the machine.
Now the code works like a charm.
Thanks BEN !!!
I am able to ping smtp.mail.yahoo.com from my system but when i send email from following code using yahoo address it gives error transport failed to connect to server.
The same code successfully sends the email from gmail account.
I am using port 465 for yahoo.
MailMessage oMsg = new MailMessage();
oMsg.From = from.Text;
oMsg.To = to.Text;
oMsg.Subject = "Hi";
oMsg.BodyFormat = MailFormat.Html;
oMsg.Body = msg.Text;
oMsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserverport", port);
oMsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserver", host);
oMsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusing", 2);
WebProxy proxy = WebProxy.GetDefaultProxy();
if (proxy.Address != null)
{
oMsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/urlproxyserver", proxy.Address.Host);
oMsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/proxyserverport", proxy.Address.Port);
}
oMsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpusessl", true);
oMsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", "1");
oMsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername",from.Text);
oMsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", pass.Text);
// ADD AN ATTACHMENT.
/* MailAttachment oAttch = new MailAttachment(path+ "\\Image.bmp", MailEncoding.Base64);
oMsg.Attachments.Add(oAttch);*/
SmtpMail.SmtpServer.Insert(0,host);
if (proxy.Address != null)
MessageBox.Show("Sending via proxy settings: " + proxy.Address.ToString());
try
{
SmtpMail.Send(oMsg);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
oMsg = null;
Any ideas why this error occurs?
Being able (or not) to ping a host does not say anything about whether you will be able to connect to a particular service on it. For that, you need to try to actually establish a connection. (And of course, the fact that you can establish a connection does not necessarily imply that the service in question is working properly.)
Usually, it's a good idea to use telnet to try connecting to the remote host on the port in question. The syntax on the command line is simply telnet host.fqdn.example.com portnumber. This will tell you if there is anything at all at the other end of the pipe responding to connection attempts, which is a first step in determining where the problem is.
Second, it's usually a good idea to trim the code to the minimal version that exhibits the problematic behavior, and include the full code to show the problematic behavior. You are using a number of variables in your code which we really know nothing about.
Some ISPs block outgoing connections to the SMTP ports on hosts other than their own mail servers, to reduce the amount of outgoing spam. Maybe there is a typo in the value in host? Maybe you are inadvertantly using some unexpected MailMessage implementation? And so on.
That said, I would definitely first try to connect to the mail server in question manually, through a proxy if you are using one to connect using that code. If that doesn't work either, then your problem at least has nothing to do with the code in the question, and you can look elsewhere (in which case one possible candidate would be ISP filters; maybe they have a list of allowed external SMTP hosts and Yahoo's isn't on it?).
I am dispatching emails at clients, notifying them for specific content deliveries and I have a problem with the containing ftp uri in mail body. I am constructing the ftp uri alongside with ftp credentials in the following format, but the credentials part is stripped away (the section user:pass#):
ftp://user:pass#server/relativepath/filename
The code is something like that:
mailTemplate += String.Format("File FTP URI: {1}<br>",
new Uri(ftpBaseLink, filename), filename);
and the email is dispatched with the following matter:
MailMessage message = new MailMessage(
mailSettings.Smtp.From,
mailTo,
subject,
mailMessage) { IsBodyHtml = true };
SmtpClient client = new SmtpClient();
client.Send(message);
Is there any clue how can I override this "normalization"?
I think that there was a general "tightening" of security a while back because of the way URLs containing user:pass were being mis-used to fool people into thinking they were clicking on a link to http://www.mybank.com when the link itself was http://www.mybank.com:blah#www.adodgysite.com/fake_bank_site. Users are wiser now, but it may be that its this "lockdown" that is affecting you.
My suggestion would be to concatenate the URI yourself, without using Uri
off the top, i'd look into what 'new Uri(ftpBaseLink, filename)' becomes as a string.