Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / Net / System / Net / Mail / SmtpClient.cs / 4 / SmtpClient.cs
namespace System.Net.Mail
{
using System;
using System.IO;
using System.Net;
using System.Collections;
using System.ComponentModel;
using System.Configuration;
using System.Net.Configuration;
using System.Threading;
using System.Security;
using System.Security.Permissions;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Net.NetworkInformation;
using System.Runtime.Versioning;
public delegate void SendCompletedEventHandler(object sender, AsyncCompletedEventArgs e);
public enum SmtpDeliveryMethod {
Network,
SpecifiedPickupDirectory,
#if !FEATURE_PAL
PickupDirectoryFromIis
#endif
}
public class SmtpClient {
string host;
int port;
bool inCall;
bool cancelled;
bool timedOut;
string targetName = null;
SmtpDeliveryMethod deliveryMethod = SmtpDeliveryMethod.Network;
string pickupDirectoryLocation = null;
SmtpTransport transport;
MailMessage message; //required to prevent premature finalization
MailWriter writer;
MailAddressCollection recipients;
SendOrPostCallback onSendCompletedDelegate;
Timer timer;
static MailSettingsSectionGroupInternal mailConfiguration;
ContextAwareResult operationCompletedResult = null;
AsyncOperation asyncOp = null;
static AsyncCallback _ContextSafeCompleteCallback = new AsyncCallback(ContextSafeCompleteCallback);
static int defaultPort = 25;
internal string clientDomain = null;
public event SendCompletedEventHandler SendCompleted;
public SmtpClient() {
if (Logging.On) Logging.Enter(Logging.Web, "SmtpClient", ".ctor", "");
try {
Initialize();
} finally {
if (Logging.On) Logging.Exit(Logging.Web, "SmtpClient", ".ctor", this);
}
}
public SmtpClient(string host) {
if (Logging.On) Logging.Enter(Logging.Web, "SmtpClient", ".ctor", "host=" + host);
try {
this.host = host;
Initialize();
} finally {
if (Logging.On) Logging.Exit(Logging.Web, "SmtpClient", ".ctor", this);
}
}
//?? should port throw or just default on 0?
public SmtpClient(string host, int port) {
if (Logging.On) Logging.Enter(Logging.Web, "SmtpClient", ".ctor", "host=" + host + ", port=" + port);
try {
if (port < 0) {
throw new ArgumentOutOfRangeException("port");
}
this.host = host;
this.port = port;
Initialize();
} finally {
if (Logging.On) Logging.Exit(Logging.Web, "SmtpClient", ".ctor", this);
}
}
void Initialize() {
if (port == defaultPort || port == 0) {
new SmtpPermission(SmtpAccess.Connect).Demand();
}
else {
new SmtpPermission(SmtpAccess.ConnectToUnrestrictedPort).Demand();
}
transport = new SmtpTransport(this);
if (Logging.On) Logging.Associate(Logging.Web, this, transport);
onSendCompletedDelegate = new SendOrPostCallback(SendCompletedWaitCallback);
if (MailConfiguration.Smtp != null)
{
if (MailConfiguration.Smtp.Network != null)
{
if (host == null || host.Length == 0) {
host = MailConfiguration.Smtp.Network.Host;
}
if (port == 0) {
port = MailConfiguration.Smtp.Network.Port;
}
transport.Credentials = MailConfiguration.Smtp.Network.Credential;
// If the config file contains a domain to be used for the
// domain element in the client's EHLO or HELO message,
// use it.
//
// We do not validate whether the domain specified is valid.
// It is up to the administrators or user to use the right
// value for their scenario.
//
// Note: per section 4.1.4 of RFC2821, the domain element of
// the HELO/EHLO should be used for logging purposes. An
// SMTP server should not decide to route an email based on
// this value.
clientDomain = MailConfiguration.Smtp.Network.ClientDomain;
if (MailConfiguration.Smtp.Network.TargetName != null)
targetName = MailConfiguration.Smtp.Network.TargetName;
}
deliveryMethod = MailConfiguration.Smtp.DeliveryMethod;
if (MailConfiguration.Smtp.SpecifiedPickupDirectory != null)
pickupDirectoryLocation = MailConfiguration.Smtp.SpecifiedPickupDirectory.PickupDirectoryLocation;
}
if (host != null && host.Length != 0) {
host = host.Trim();
}
if (port == 0) {
port = defaultPort;
}
if (clientDomain == null) {
// We use the local host name as the default client domain
// for the client's EHLO or HELO message. This limits the
// information about the host that we share. Additionally, the
// FQDN is not available to us or useful to the server (internal
// machine connecting to public server).
clientDomain = IPGlobalProperties.InternalGetIPGlobalProperties().HostName;
}
if (this.targetName == null)
targetName = "SMTPSVC/" + host;
}
public string Host {
get {
return host;
}
set {
if (InCall) {
throw new InvalidOperationException(SR.GetString(SR.SmtpInvalidOperationDuringSend));
}
if (value == null)
{
throw new ArgumentNullException("value");
}
if (value == String.Empty)
{
throw new ArgumentException(SR.GetString(SR.net_emptystringset), "value");
}
host = value.Trim();
}
}
public int Port {
get {
return port;
}
set {
if (InCall) {
throw new InvalidOperationException(SR.GetString(SR.SmtpInvalidOperationDuringSend));
}
if (value <= 0) {
throw new ArgumentOutOfRangeException("value");
}
if (value != defaultPort) {
new SmtpPermission(SmtpAccess.ConnectToUnrestrictedPort).Demand();
}
port = value;
}
}
public bool UseDefaultCredentials {
get {
return (transport.Credentials is SystemNetworkCredential) ? true : false;
}
set {
if (InCall) {
throw new InvalidOperationException(SR.GetString(SR.SmtpInvalidOperationDuringSend));
}
transport.Credentials = value ? CredentialCache.DefaultNetworkCredentials : null;
}
}
public ICredentialsByHost Credentials {
get {
return transport.Credentials;
}
set {
if (InCall) {
throw new InvalidOperationException(SR.GetString(SR.SmtpInvalidOperationDuringSend));
}
transport.Credentials = value;
}
}
public int Timeout {
get {
return transport.Timeout;
}
set {
if (InCall) {
throw new InvalidOperationException(SR.GetString(SR.SmtpInvalidOperationDuringSend));
}
if (value < 0)
{
throw new ArgumentOutOfRangeException("value");
}
transport.Timeout = value;
}
}
public ServicePoint ServicePoint {
get {
CheckHostAndPort();
return ServicePointManager.FindServicePoint(host, port);
}
}
public SmtpDeliveryMethod DeliveryMethod {
get {
return deliveryMethod;
}
set {
deliveryMethod = value;
}
}
public string PickupDirectoryLocation {
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
get {
return pickupDirectoryLocation;
}
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
set {
pickupDirectoryLocation = value;
}
}
///
/// Set to true if we need SSL
///
public bool EnableSsl {
get {
return transport.EnableSsl;
}
set {
transport.EnableSsl = value;
}
}
///
/// Certificates used by the client for establishing an SSL connection with the server.
///
public X509CertificateCollection ClientCertificates {
get {
return transport.ClientCertificates;
}
}
public string TargetName {
set { this.targetName = value; }
get { return this.targetName; }
}
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
internal MailWriter GetFileMailWriter(string pickupDirectory)
{
if (Logging.On) Logging.PrintInfo(Logging.Web, "SmtpClient.Send() pickupDirectory=" + pickupDirectory);
if (!Path.IsPathRooted(pickupDirectory))
throw new SmtpException(SR.GetString(SR.SmtpNeedAbsolutePickupDirectory));
string filename;
string pathAndFilename;
while (true) {
filename = Guid.NewGuid().ToString() + ".eml";
pathAndFilename = Path.Combine(pickupDirectory, filename);
if (!File.Exists(pathAndFilename))
break;
}
FileStream fileStream = new FileStream(pathAndFilename, FileMode.CreateNew);
return new MailWriter(fileStream);
}
protected void OnSendCompleted(AsyncCompletedEventArgs e)
{
if (SendCompleted != null) {
SendCompleted(this, e);
}
}
void SendCompletedWaitCallback(object operationState) {
OnSendCompleted((AsyncCompletedEventArgs)operationState);
}
public void Send(string from, string recipients, string subject, string body) {
//validation happends in MailMessage constructor
MailMessage mailMessage = new MailMessage(from, recipients, subject, body);
Send(mailMessage);
}
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
public void Send(MailMessage message) {
if (Logging.On) Logging.Enter(Logging.Web, this, "Send", message);
try {
if (Logging.On) Logging.PrintInfo(Logging.Web, this, "Send", "DeliveryMethod=" + DeliveryMethod.ToString());
if (Logging.On) Logging.Associate(Logging.Web, this, message);
SmtpFailedRecipientException recipientException = null;
if (InCall) {
throw new InvalidOperationException(SR.GetString(SR.net_inasync));
}
if (message == null) {
throw new ArgumentNullException("message");
}
if (DeliveryMethod == SmtpDeliveryMethod.Network)
CheckHostAndPort();
MailAddressCollection recipients = new MailAddressCollection();
if (message.From == null) {
throw new InvalidOperationException(SR.GetString(SR.SmtpFromRequired));
}
if (message.To != null) {
foreach (MailAddress address in message.To) {
recipients.Add(address);
}
}
if (message.Bcc != null) {
foreach (MailAddress address in message.Bcc) {
recipients.Add(address);
}
}
if (message.CC != null) {
foreach (MailAddress address in message.CC) {
recipients.Add(address);
}
}
if (recipients.Count == 0) {
throw new InvalidOperationException(SR.GetString(SR.SmtpRecipientRequired));
}
transport.IdentityRequired = false; // everything completes on the same thread.
try {
InCall = true;
timedOut = false;
timer = new Timer(new TimerCallback(this.TimeOutCallback), null, Timeout, Timeout);
MailWriter writer;
switch (DeliveryMethod) {
case SmtpDeliveryMethod.SpecifiedPickupDirectory:
if (EnableSsl)
throw new SmtpException(SR.GetString(SR.SmtpPickupDirectoryDoesnotSupportSsl));
writer = GetFileMailWriter(PickupDirectoryLocation);
break;
#if !FEATURE_PAL
case SmtpDeliveryMethod.PickupDirectoryFromIis:
if (EnableSsl)
throw new SmtpException(SR.GetString(SR.SmtpPickupDirectoryDoesnotSupportSsl));
writer = GetFileMailWriter(IisPickupDirectory.GetPickupDirectory());
break;
#endif // !FEATURE_PAL
case SmtpDeliveryMethod.Network:
default:
GetConnection();
writer = transport.SendMail(message.Sender != null ? message.Sender : message.From, recipients, message.BuildDeliveryStatusNotificationString(), out recipientException);
break;
}
this.message = message;
message.Send(writer, DeliveryMethod != SmtpDeliveryMethod.Network);
writer.Close();
transport.ReleaseConnection();
//throw if we couldn't send to any of the recipients
if (DeliveryMethod == SmtpDeliveryMethod.Network)
if (recipientException != null)
throw recipientException;
}
catch (Exception e) {
if (Logging.On) Logging.Exception(Logging.Web, this, "Send", e);
if (e is SmtpFailedRecipientException && !((SmtpFailedRecipientException)e).fatal) {
throw;
}
Abort();
if (timedOut) {
throw new SmtpException(SR.GetString(SR.net_timeout));
}
if (e is SecurityException ||
e is AuthenticationException ||
e is SmtpException)
{
throw;
}
throw new SmtpException(SR.GetString(SR.SmtpSendMailFailure), e);
}
finally {
InCall = false;
if (timer != null) {
timer.Dispose();
}
}
} finally {
if (Logging.On) Logging.Exit(Logging.Web, this, "Send", null);
}
}
[HostProtection(ExternalThreading = true)]
public void SendAsync(string from, string recipients, string subject, string body, object userToken) {
SendAsync(new MailMessage(from, recipients, subject, body), userToken);
}
[HostProtection(ExternalThreading = true)]
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
public void SendAsync(MailMessage message, object userToken) {
if (Logging.On) Logging.Enter(Logging.Web, this, "SendAsync", "DeliveryMethod=" + DeliveryMethod.ToString());
GlobalLog.Enter("SmtpClient#" + ValidationHelper.HashString(this) + "::SendAsync Transport#" + ValidationHelper.HashString(transport));
try {
if (InCall) {
throw new InvalidOperationException(SR.GetString(SR.net_inasync));
}
if (message == null) {
throw new ArgumentNullException("message");
}
if (DeliveryMethod == SmtpDeliveryMethod.Network)
CheckHostAndPort();
recipients = new MailAddressCollection();
if (message.From == null) {
throw new InvalidOperationException(SR.GetString(SR.SmtpFromRequired));
}
if (message.To != null) {
foreach (MailAddress address in message.To) {
recipients.Add(address);
}
}
if (message.Bcc != null) {
foreach (MailAddress address in message.Bcc) {
recipients.Add(address);
}
}
if (message.CC != null) {
foreach (MailAddress address in message.CC) {
recipients.Add(address);
}
}
if (recipients.Count == 0) {
throw new InvalidOperationException(SR.GetString(SR.SmtpRecipientRequired));
}
try {
InCall = true;
cancelled = false;
this.message = message;
#if !FEATURE_PAL
CredentialCache cache;
// Skip token capturing if no credentials are used or they don't include a default one.
// Also do capture the token if ICredential is not of CredentialCache type so we don't know what the exact credential response will be.
transport.IdentityRequired = Credentials != null && ComNetOS.IsWinNt && (Credentials is SystemNetworkCredential || (cache = Credentials as CredentialCache) == null || cache.IsDefaultInCache);
#endif // !FEATURE_PAL
asyncOp = AsyncOperationManager.CreateOperation(userToken);
switch (DeliveryMethod) {
case SmtpDeliveryMethod.SpecifiedPickupDirectory:
{
if (EnableSsl)
throw new SmtpException(SR.GetString(SR.SmtpPickupDirectoryDoesnotSupportSsl));
writer = GetFileMailWriter(PickupDirectoryLocation);
message.Send(writer, DeliveryMethod != SmtpDeliveryMethod.Network);
if (writer != null)
writer.Close();
transport.ReleaseConnection();
AsyncCompletedEventArgs eventArgs = new AsyncCompletedEventArgs(null, false, asyncOp.UserSuppliedState);
InCall = false;
asyncOp.PostOperationCompleted(onSendCompletedDelegate, eventArgs);
break;
}
#if !FEATURE_PAL
case SmtpDeliveryMethod.PickupDirectoryFromIis:
{
if (EnableSsl)
throw new SmtpException(SR.GetString(SR.SmtpPickupDirectoryDoesnotSupportSsl));
writer = GetFileMailWriter(IisPickupDirectory.GetPickupDirectory());
message.Send(writer, DeliveryMethod != SmtpDeliveryMethod.Network);
if (writer != null)
writer.Close();
transport.ReleaseConnection();
AsyncCompletedEventArgs eventArgs = new AsyncCompletedEventArgs(null, false, asyncOp.UserSuppliedState);
InCall = false;
asyncOp.PostOperationCompleted(onSendCompletedDelegate, eventArgs);
break;
}
#endif // !FEATURE_PAL
case SmtpDeliveryMethod.Network:
default:
operationCompletedResult = new ContextAwareResult(transport.IdentityRequired, true, null, this, _ContextSafeCompleteCallback);
lock (operationCompletedResult.StartPostingAsyncOp())
{
GlobalLog.Print("SmtpClient#" + ValidationHelper.HashString(this) + "::SendAsync calling BeginConnect. Transport#" + ValidationHelper.HashString(transport));
transport.BeginGetConnection(host, port, operationCompletedResult, ConnectCallback, operationCompletedResult);
operationCompletedResult.FinishPostingAsyncOp();
}
break;
}
}
catch (Exception e) {
InCall = false;
if (Logging.On) Logging.Exception(Logging.Web, this, "Send", e);
if (e is SmtpFailedRecipientException && !((SmtpFailedRecipientException)e).fatal) {
throw;
}
Abort();
if (timedOut) {
throw new SmtpException(SR.GetString(SR.net_timeout));
}
if (e is SecurityException ||
e is AuthenticationException ||
e is SmtpException)
{
throw;
}
throw new SmtpException(SR.GetString(SR.SmtpSendMailFailure), e);
}
} finally {
if (Logging.On) Logging.Exit(Logging.Web, this, "SendAsync", null);
GlobalLog.Leave("SmtpClient#" + ValidationHelper.HashString(this) + "::SendAsync");
}
}
public void SendAsyncCancel() {
if (Logging.On) Logging.Enter(Logging.Web, this, "SendAsyncCancel", null);
GlobalLog.Enter("SmtpClient#" + ValidationHelper.HashString(this) + "::SendAsyncCancel");
try {
if (!InCall || cancelled) {
return;
}
cancelled = true;
Abort();
} finally {
if (Logging.On) Logging.Exit(Logging.Web, this, "SendAsyncCancel", null);
GlobalLog.Leave("SmtpClient#" + ValidationHelper.HashString(this) + "::SendAsyncCancel");
}
}
//*********************************
// private methods
//********************************
internal bool InCall {
get {
return inCall;
}
set {
inCall = value;
}
}
internal static MailSettingsSectionGroupInternal MailConfiguration {
get {
if (mailConfiguration == null) {
mailConfiguration = MailSettingsSectionGroupInternal.GetSection();
}
return mailConfiguration;
}
}
void CheckHostAndPort() {
if (host == null || host.Length == 0) {
throw new InvalidOperationException(SR.GetString(SR.UnspecifiedHost));
}
if (port == 0) {
throw new InvalidOperationException(SR.GetString(SR.InvalidPort));
}
}
void TimeOutCallback(object state) {
if (!timedOut) {
timedOut = true;
Abort();
}
}
void Complete(Exception exception, IAsyncResult result) {
ContextAwareResult operationCompletedResult = (ContextAwareResult)result.AsyncState;
GlobalLog.Enter("SmtpClient#" + ValidationHelper.HashString(this) + "::Complete");
try {
if (cancelled) {
//any exceptions were probably caused by cancellation, clear it.
exception = null;
Abort();
}
// A failed recipient exception is benign
else if (exception != null && (!(exception is SmtpFailedRecipientException) || ((SmtpFailedRecipientException)exception).fatal))
{
GlobalLog.Print("SmtpClient#" + ValidationHelper.HashString(this) + "::Complete Exception: " + exception.ToString());
Abort();
if (!(exception is SmtpException)) {
exception = new SmtpException(SR.GetString(SR.SmtpSendMailFailure), exception);
}
}
else {
if (writer != null) {
writer.Close();
}
transport.ReleaseConnection();
}
}
finally {
operationCompletedResult.InvokeCallback(exception);
}
GlobalLog.Leave("SmtpClient#" + ValidationHelper.HashString(this) + "::Complete");
}
static void ContextSafeCompleteCallback(IAsyncResult ar)
{
ContextAwareResult result = (ContextAwareResult)ar;
SmtpClient client = (SmtpClient)ar.AsyncState;
Exception exception = result.Result as Exception;
AsyncOperation asyncOp = client.asyncOp;
AsyncCompletedEventArgs eventArgs = new AsyncCompletedEventArgs(exception, client.cancelled, asyncOp.UserSuppliedState);
client.InCall = false;
asyncOp.PostOperationCompleted(client.onSendCompletedDelegate, eventArgs);
}
/*
void DisconnectCallback(IAsyncResult result) {
SmtpClient client = (SmtpClient)result.AsyncState;
try {
client.transport.EndDisconnect(result);
}
catch (Exception e) {
Complete(e);
return;
}
Complete(null);
}
*/
void SendMessageCallback(IAsyncResult result) {
GlobalLog.Enter("SmtpClient#" + ValidationHelper.HashString(this) + "::SendMessageCallback");
try {
message.EndSend(result);
Complete(null, result);
}
catch (Exception e) {
Complete(e, result);
}
GlobalLog.Leave("SmtpClient#" + ValidationHelper.HashString(this) + "::SendMessageCallback");
}
void SendMailCallback(IAsyncResult result) {
GlobalLog.Enter("SmtpClient#" + ValidationHelper.HashString(this) + "::SendMailCallback");
try {
writer = transport.EndSendMail(result);
}
catch (Exception e)
{
// Note the difference between the singular and plural FailedRecipient exceptions.
// Only fail immediately if we couldn't send to any recipients.
if (!(e is SmtpFailedRecipientException) || ((SmtpFailedRecipientException)e).fatal)
{
Complete(e, result);
GlobalLog.Leave("SmtpClient#" + ValidationHelper.HashString(this) + "::SendMailCallback");
return;
}
}
catch
{
// Note the difference between the singular and plural FailedRecipient exceptions.
// Only fail immediately if we couldn't send to any recipients.
Complete(new Exception(SR.GetString(SR.net_nonClsCompliantException)), result);
GlobalLog.Leave("SmtpClient#" + ValidationHelper.HashString(this) + "::SendMailCallback");
return;
}
try {
if (cancelled) {
Complete(null, result);
}
else {
message.BeginSend(writer, DeliveryMethod != SmtpDeliveryMethod.Network, new AsyncCallback(SendMessageCallback), result.AsyncState);
}
}
catch (Exception e) {
Complete(e, result);
}
GlobalLog.Leave("SmtpClient#" + ValidationHelper.HashString(this) + "::SendMailCallback");
}
void ConnectCallback(IAsyncResult result) {
GlobalLog.Enter("SmtpClient#" + ValidationHelper.HashString(this) + "::ConnectCallback");
try {
transport.EndGetConnection(result);
if (cancelled) {
Complete(null, result);
}
else {
transport.BeginSendMail(message.Sender != null ? message.Sender : message.From, recipients, message.BuildDeliveryStatusNotificationString(), new AsyncCallback(SendMailCallback), result.AsyncState);
}
}
catch (Exception e) {
Complete(e, result);
}
GlobalLog.Leave("SmtpClient#" + ValidationHelper.HashString(this) + "::ConnectCallback");
}
void GetConnection() {
if (!transport.IsConnected) {
transport.GetConnection(host, port);
}
}
void Abort() {
try {
transport.Abort();
}
catch {
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
namespace System.Net.Mail
{
using System;
using System.IO;
using System.Net;
using System.Collections;
using System.ComponentModel;
using System.Configuration;
using System.Net.Configuration;
using System.Threading;
using System.Security;
using System.Security.Permissions;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Net.NetworkInformation;
using System.Runtime.Versioning;
public delegate void SendCompletedEventHandler(object sender, AsyncCompletedEventArgs e);
public enum SmtpDeliveryMethod {
Network,
SpecifiedPickupDirectory,
#if !FEATURE_PAL
PickupDirectoryFromIis
#endif
}
public class SmtpClient {
string host;
int port;
bool inCall;
bool cancelled;
bool timedOut;
string targetName = null;
SmtpDeliveryMethod deliveryMethod = SmtpDeliveryMethod.Network;
string pickupDirectoryLocation = null;
SmtpTransport transport;
MailMessage message; //required to prevent premature finalization
MailWriter writer;
MailAddressCollection recipients;
SendOrPostCallback onSendCompletedDelegate;
Timer timer;
static MailSettingsSectionGroupInternal mailConfiguration;
ContextAwareResult operationCompletedResult = null;
AsyncOperation asyncOp = null;
static AsyncCallback _ContextSafeCompleteCallback = new AsyncCallback(ContextSafeCompleteCallback);
static int defaultPort = 25;
internal string clientDomain = null;
public event SendCompletedEventHandler SendCompleted;
public SmtpClient() {
if (Logging.On) Logging.Enter(Logging.Web, "SmtpClient", ".ctor", "");
try {
Initialize();
} finally {
if (Logging.On) Logging.Exit(Logging.Web, "SmtpClient", ".ctor", this);
}
}
public SmtpClient(string host) {
if (Logging.On) Logging.Enter(Logging.Web, "SmtpClient", ".ctor", "host=" + host);
try {
this.host = host;
Initialize();
} finally {
if (Logging.On) Logging.Exit(Logging.Web, "SmtpClient", ".ctor", this);
}
}
//?? should port throw or just default on 0?
public SmtpClient(string host, int port) {
if (Logging.On) Logging.Enter(Logging.Web, "SmtpClient", ".ctor", "host=" + host + ", port=" + port);
try {
if (port < 0) {
throw new ArgumentOutOfRangeException("port");
}
this.host = host;
this.port = port;
Initialize();
} finally {
if (Logging.On) Logging.Exit(Logging.Web, "SmtpClient", ".ctor", this);
}
}
void Initialize() {
if (port == defaultPort || port == 0) {
new SmtpPermission(SmtpAccess.Connect).Demand();
}
else {
new SmtpPermission(SmtpAccess.ConnectToUnrestrictedPort).Demand();
}
transport = new SmtpTransport(this);
if (Logging.On) Logging.Associate(Logging.Web, this, transport);
onSendCompletedDelegate = new SendOrPostCallback(SendCompletedWaitCallback);
if (MailConfiguration.Smtp != null)
{
if (MailConfiguration.Smtp.Network != null)
{
if (host == null || host.Length == 0) {
host = MailConfiguration.Smtp.Network.Host;
}
if (port == 0) {
port = MailConfiguration.Smtp.Network.Port;
}
transport.Credentials = MailConfiguration.Smtp.Network.Credential;
// If the config file contains a domain to be used for the
// domain element in the client's EHLO or HELO message,
// use it.
//
// We do not validate whether the domain specified is valid.
// It is up to the administrators or user to use the right
// value for their scenario.
//
// Note: per section 4.1.4 of RFC2821, the domain element of
// the HELO/EHLO should be used for logging purposes. An
// SMTP server should not decide to route an email based on
// this value.
clientDomain = MailConfiguration.Smtp.Network.ClientDomain;
if (MailConfiguration.Smtp.Network.TargetName != null)
targetName = MailConfiguration.Smtp.Network.TargetName;
}
deliveryMethod = MailConfiguration.Smtp.DeliveryMethod;
if (MailConfiguration.Smtp.SpecifiedPickupDirectory != null)
pickupDirectoryLocation = MailConfiguration.Smtp.SpecifiedPickupDirectory.PickupDirectoryLocation;
}
if (host != null && host.Length != 0) {
host = host.Trim();
}
if (port == 0) {
port = defaultPort;
}
if (clientDomain == null) {
// We use the local host name as the default client domain
// for the client's EHLO or HELO message. This limits the
// information about the host that we share. Additionally, the
// FQDN is not available to us or useful to the server (internal
// machine connecting to public server).
clientDomain = IPGlobalProperties.InternalGetIPGlobalProperties().HostName;
}
if (this.targetName == null)
targetName = "SMTPSVC/" + host;
}
public string Host {
get {
return host;
}
set {
if (InCall) {
throw new InvalidOperationException(SR.GetString(SR.SmtpInvalidOperationDuringSend));
}
if (value == null)
{
throw new ArgumentNullException("value");
}
if (value == String.Empty)
{
throw new ArgumentException(SR.GetString(SR.net_emptystringset), "value");
}
host = value.Trim();
}
}
public int Port {
get {
return port;
}
set {
if (InCall) {
throw new InvalidOperationException(SR.GetString(SR.SmtpInvalidOperationDuringSend));
}
if (value <= 0) {
throw new ArgumentOutOfRangeException("value");
}
if (value != defaultPort) {
new SmtpPermission(SmtpAccess.ConnectToUnrestrictedPort).Demand();
}
port = value;
}
}
public bool UseDefaultCredentials {
get {
return (transport.Credentials is SystemNetworkCredential) ? true : false;
}
set {
if (InCall) {
throw new InvalidOperationException(SR.GetString(SR.SmtpInvalidOperationDuringSend));
}
transport.Credentials = value ? CredentialCache.DefaultNetworkCredentials : null;
}
}
public ICredentialsByHost Credentials {
get {
return transport.Credentials;
}
set {
if (InCall) {
throw new InvalidOperationException(SR.GetString(SR.SmtpInvalidOperationDuringSend));
}
transport.Credentials = value;
}
}
public int Timeout {
get {
return transport.Timeout;
}
set {
if (InCall) {
throw new InvalidOperationException(SR.GetString(SR.SmtpInvalidOperationDuringSend));
}
if (value < 0)
{
throw new ArgumentOutOfRangeException("value");
}
transport.Timeout = value;
}
}
public ServicePoint ServicePoint {
get {
CheckHostAndPort();
return ServicePointManager.FindServicePoint(host, port);
}
}
public SmtpDeliveryMethod DeliveryMethod {
get {
return deliveryMethod;
}
set {
deliveryMethod = value;
}
}
public string PickupDirectoryLocation {
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
get {
return pickupDirectoryLocation;
}
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
set {
pickupDirectoryLocation = value;
}
}
///
/// Set to true if we need SSL
///
public bool EnableSsl {
get {
return transport.EnableSsl;
}
set {
transport.EnableSsl = value;
}
}
///
/// Certificates used by the client for establishing an SSL connection with the server.
///
public X509CertificateCollection ClientCertificates {
get {
return transport.ClientCertificates;
}
}
public string TargetName {
set { this.targetName = value; }
get { return this.targetName; }
}
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
internal MailWriter GetFileMailWriter(string pickupDirectory)
{
if (Logging.On) Logging.PrintInfo(Logging.Web, "SmtpClient.Send() pickupDirectory=" + pickupDirectory);
if (!Path.IsPathRooted(pickupDirectory))
throw new SmtpException(SR.GetString(SR.SmtpNeedAbsolutePickupDirectory));
string filename;
string pathAndFilename;
while (true) {
filename = Guid.NewGuid().ToString() + ".eml";
pathAndFilename = Path.Combine(pickupDirectory, filename);
if (!File.Exists(pathAndFilename))
break;
}
FileStream fileStream = new FileStream(pathAndFilename, FileMode.CreateNew);
return new MailWriter(fileStream);
}
protected void OnSendCompleted(AsyncCompletedEventArgs e)
{
if (SendCompleted != null) {
SendCompleted(this, e);
}
}
void SendCompletedWaitCallback(object operationState) {
OnSendCompleted((AsyncCompletedEventArgs)operationState);
}
public void Send(string from, string recipients, string subject, string body) {
//validation happends in MailMessage constructor
MailMessage mailMessage = new MailMessage(from, recipients, subject, body);
Send(mailMessage);
}
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
public void Send(MailMessage message) {
if (Logging.On) Logging.Enter(Logging.Web, this, "Send", message);
try {
if (Logging.On) Logging.PrintInfo(Logging.Web, this, "Send", "DeliveryMethod=" + DeliveryMethod.ToString());
if (Logging.On) Logging.Associate(Logging.Web, this, message);
SmtpFailedRecipientException recipientException = null;
if (InCall) {
throw new InvalidOperationException(SR.GetString(SR.net_inasync));
}
if (message == null) {
throw new ArgumentNullException("message");
}
if (DeliveryMethod == SmtpDeliveryMethod.Network)
CheckHostAndPort();
MailAddressCollection recipients = new MailAddressCollection();
if (message.From == null) {
throw new InvalidOperationException(SR.GetString(SR.SmtpFromRequired));
}
if (message.To != null) {
foreach (MailAddress address in message.To) {
recipients.Add(address);
}
}
if (message.Bcc != null) {
foreach (MailAddress address in message.Bcc) {
recipients.Add(address);
}
}
if (message.CC != null) {
foreach (MailAddress address in message.CC) {
recipients.Add(address);
}
}
if (recipients.Count == 0) {
throw new InvalidOperationException(SR.GetString(SR.SmtpRecipientRequired));
}
transport.IdentityRequired = false; // everything completes on the same thread.
try {
InCall = true;
timedOut = false;
timer = new Timer(new TimerCallback(this.TimeOutCallback), null, Timeout, Timeout);
MailWriter writer;
switch (DeliveryMethod) {
case SmtpDeliveryMethod.SpecifiedPickupDirectory:
if (EnableSsl)
throw new SmtpException(SR.GetString(SR.SmtpPickupDirectoryDoesnotSupportSsl));
writer = GetFileMailWriter(PickupDirectoryLocation);
break;
#if !FEATURE_PAL
case SmtpDeliveryMethod.PickupDirectoryFromIis:
if (EnableSsl)
throw new SmtpException(SR.GetString(SR.SmtpPickupDirectoryDoesnotSupportSsl));
writer = GetFileMailWriter(IisPickupDirectory.GetPickupDirectory());
break;
#endif // !FEATURE_PAL
case SmtpDeliveryMethod.Network:
default:
GetConnection();
writer = transport.SendMail(message.Sender != null ? message.Sender : message.From, recipients, message.BuildDeliveryStatusNotificationString(), out recipientException);
break;
}
this.message = message;
message.Send(writer, DeliveryMethod != SmtpDeliveryMethod.Network);
writer.Close();
transport.ReleaseConnection();
//throw if we couldn't send to any of the recipients
if (DeliveryMethod == SmtpDeliveryMethod.Network)
if (recipientException != null)
throw recipientException;
}
catch (Exception e) {
if (Logging.On) Logging.Exception(Logging.Web, this, "Send", e);
if (e is SmtpFailedRecipientException && !((SmtpFailedRecipientException)e).fatal) {
throw;
}
Abort();
if (timedOut) {
throw new SmtpException(SR.GetString(SR.net_timeout));
}
if (e is SecurityException ||
e is AuthenticationException ||
e is SmtpException)
{
throw;
}
throw new SmtpException(SR.GetString(SR.SmtpSendMailFailure), e);
}
finally {
InCall = false;
if (timer != null) {
timer.Dispose();
}
}
} finally {
if (Logging.On) Logging.Exit(Logging.Web, this, "Send", null);
}
}
[HostProtection(ExternalThreading = true)]
public void SendAsync(string from, string recipients, string subject, string body, object userToken) {
SendAsync(new MailMessage(from, recipients, subject, body), userToken);
}
[HostProtection(ExternalThreading = true)]
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
public void SendAsync(MailMessage message, object userToken) {
if (Logging.On) Logging.Enter(Logging.Web, this, "SendAsync", "DeliveryMethod=" + DeliveryMethod.ToString());
GlobalLog.Enter("SmtpClient#" + ValidationHelper.HashString(this) + "::SendAsync Transport#" + ValidationHelper.HashString(transport));
try {
if (InCall) {
throw new InvalidOperationException(SR.GetString(SR.net_inasync));
}
if (message == null) {
throw new ArgumentNullException("message");
}
if (DeliveryMethod == SmtpDeliveryMethod.Network)
CheckHostAndPort();
recipients = new MailAddressCollection();
if (message.From == null) {
throw new InvalidOperationException(SR.GetString(SR.SmtpFromRequired));
}
if (message.To != null) {
foreach (MailAddress address in message.To) {
recipients.Add(address);
}
}
if (message.Bcc != null) {
foreach (MailAddress address in message.Bcc) {
recipients.Add(address);
}
}
if (message.CC != null) {
foreach (MailAddress address in message.CC) {
recipients.Add(address);
}
}
if (recipients.Count == 0) {
throw new InvalidOperationException(SR.GetString(SR.SmtpRecipientRequired));
}
try {
InCall = true;
cancelled = false;
this.message = message;
#if !FEATURE_PAL
CredentialCache cache;
// Skip token capturing if no credentials are used or they don't include a default one.
// Also do capture the token if ICredential is not of CredentialCache type so we don't know what the exact credential response will be.
transport.IdentityRequired = Credentials != null && ComNetOS.IsWinNt && (Credentials is SystemNetworkCredential || (cache = Credentials as CredentialCache) == null || cache.IsDefaultInCache);
#endif // !FEATURE_PAL
asyncOp = AsyncOperationManager.CreateOperation(userToken);
switch (DeliveryMethod) {
case SmtpDeliveryMethod.SpecifiedPickupDirectory:
{
if (EnableSsl)
throw new SmtpException(SR.GetString(SR.SmtpPickupDirectoryDoesnotSupportSsl));
writer = GetFileMailWriter(PickupDirectoryLocation);
message.Send(writer, DeliveryMethod != SmtpDeliveryMethod.Network);
if (writer != null)
writer.Close();
transport.ReleaseConnection();
AsyncCompletedEventArgs eventArgs = new AsyncCompletedEventArgs(null, false, asyncOp.UserSuppliedState);
InCall = false;
asyncOp.PostOperationCompleted(onSendCompletedDelegate, eventArgs);
break;
}
#if !FEATURE_PAL
case SmtpDeliveryMethod.PickupDirectoryFromIis:
{
if (EnableSsl)
throw new SmtpException(SR.GetString(SR.SmtpPickupDirectoryDoesnotSupportSsl));
writer = GetFileMailWriter(IisPickupDirectory.GetPickupDirectory());
message.Send(writer, DeliveryMethod != SmtpDeliveryMethod.Network);
if (writer != null)
writer.Close();
transport.ReleaseConnection();
AsyncCompletedEventArgs eventArgs = new AsyncCompletedEventArgs(null, false, asyncOp.UserSuppliedState);
InCall = false;
asyncOp.PostOperationCompleted(onSendCompletedDelegate, eventArgs);
break;
}
#endif // !FEATURE_PAL
case SmtpDeliveryMethod.Network:
default:
operationCompletedResult = new ContextAwareResult(transport.IdentityRequired, true, null, this, _ContextSafeCompleteCallback);
lock (operationCompletedResult.StartPostingAsyncOp())
{
GlobalLog.Print("SmtpClient#" + ValidationHelper.HashString(this) + "::SendAsync calling BeginConnect. Transport#" + ValidationHelper.HashString(transport));
transport.BeginGetConnection(host, port, operationCompletedResult, ConnectCallback, operationCompletedResult);
operationCompletedResult.FinishPostingAsyncOp();
}
break;
}
}
catch (Exception e) {
InCall = false;
if (Logging.On) Logging.Exception(Logging.Web, this, "Send", e);
if (e is SmtpFailedRecipientException && !((SmtpFailedRecipientException)e).fatal) {
throw;
}
Abort();
if (timedOut) {
throw new SmtpException(SR.GetString(SR.net_timeout));
}
if (e is SecurityException ||
e is AuthenticationException ||
e is SmtpException)
{
throw;
}
throw new SmtpException(SR.GetString(SR.SmtpSendMailFailure), e);
}
} finally {
if (Logging.On) Logging.Exit(Logging.Web, this, "SendAsync", null);
GlobalLog.Leave("SmtpClient#" + ValidationHelper.HashString(this) + "::SendAsync");
}
}
public void SendAsyncCancel() {
if (Logging.On) Logging.Enter(Logging.Web, this, "SendAsyncCancel", null);
GlobalLog.Enter("SmtpClient#" + ValidationHelper.HashString(this) + "::SendAsyncCancel");
try {
if (!InCall || cancelled) {
return;
}
cancelled = true;
Abort();
} finally {
if (Logging.On) Logging.Exit(Logging.Web, this, "SendAsyncCancel", null);
GlobalLog.Leave("SmtpClient#" + ValidationHelper.HashString(this) + "::SendAsyncCancel");
}
}
//*********************************
// private methods
//********************************
internal bool InCall {
get {
return inCall;
}
set {
inCall = value;
}
}
internal static MailSettingsSectionGroupInternal MailConfiguration {
get {
if (mailConfiguration == null) {
mailConfiguration = MailSettingsSectionGroupInternal.GetSection();
}
return mailConfiguration;
}
}
void CheckHostAndPort() {
if (host == null || host.Length == 0) {
throw new InvalidOperationException(SR.GetString(SR.UnspecifiedHost));
}
if (port == 0) {
throw new InvalidOperationException(SR.GetString(SR.InvalidPort));
}
}
void TimeOutCallback(object state) {
if (!timedOut) {
timedOut = true;
Abort();
}
}
void Complete(Exception exception, IAsyncResult result) {
ContextAwareResult operationCompletedResult = (ContextAwareResult)result.AsyncState;
GlobalLog.Enter("SmtpClient#" + ValidationHelper.HashString(this) + "::Complete");
try {
if (cancelled) {
//any exceptions were probably caused by cancellation, clear it.
exception = null;
Abort();
}
// A failed recipient exception is benign
else if (exception != null && (!(exception is SmtpFailedRecipientException) || ((SmtpFailedRecipientException)exception).fatal))
{
GlobalLog.Print("SmtpClient#" + ValidationHelper.HashString(this) + "::Complete Exception: " + exception.ToString());
Abort();
if (!(exception is SmtpException)) {
exception = new SmtpException(SR.GetString(SR.SmtpSendMailFailure), exception);
}
}
else {
if (writer != null) {
writer.Close();
}
transport.ReleaseConnection();
}
}
finally {
operationCompletedResult.InvokeCallback(exception);
}
GlobalLog.Leave("SmtpClient#" + ValidationHelper.HashString(this) + "::Complete");
}
static void ContextSafeCompleteCallback(IAsyncResult ar)
{
ContextAwareResult result = (ContextAwareResult)ar;
SmtpClient client = (SmtpClient)ar.AsyncState;
Exception exception = result.Result as Exception;
AsyncOperation asyncOp = client.asyncOp;
AsyncCompletedEventArgs eventArgs = new AsyncCompletedEventArgs(exception, client.cancelled, asyncOp.UserSuppliedState);
client.InCall = false;
asyncOp.PostOperationCompleted(client.onSendCompletedDelegate, eventArgs);
}
/*
void DisconnectCallback(IAsyncResult result) {
SmtpClient client = (SmtpClient)result.AsyncState;
try {
client.transport.EndDisconnect(result);
}
catch (Exception e) {
Complete(e);
return;
}
Complete(null);
}
*/
void SendMessageCallback(IAsyncResult result) {
GlobalLog.Enter("SmtpClient#" + ValidationHelper.HashString(this) + "::SendMessageCallback");
try {
message.EndSend(result);
Complete(null, result);
}
catch (Exception e) {
Complete(e, result);
}
GlobalLog.Leave("SmtpClient#" + ValidationHelper.HashString(this) + "::SendMessageCallback");
}
void SendMailCallback(IAsyncResult result) {
GlobalLog.Enter("SmtpClient#" + ValidationHelper.HashString(this) + "::SendMailCallback");
try {
writer = transport.EndSendMail(result);
}
catch (Exception e)
{
// Note the difference between the singular and plural FailedRecipient exceptions.
// Only fail immediately if we couldn't send to any recipients.
if (!(e is SmtpFailedRecipientException) || ((SmtpFailedRecipientException)e).fatal)
{
Complete(e, result);
GlobalLog.Leave("SmtpClient#" + ValidationHelper.HashString(this) + "::SendMailCallback");
return;
}
}
catch
{
// Note the difference between the singular and plural FailedRecipient exceptions.
// Only fail immediately if we couldn't send to any recipients.
Complete(new Exception(SR.GetString(SR.net_nonClsCompliantException)), result);
GlobalLog.Leave("SmtpClient#" + ValidationHelper.HashString(this) + "::SendMailCallback");
return;
}
try {
if (cancelled) {
Complete(null, result);
}
else {
message.BeginSend(writer, DeliveryMethod != SmtpDeliveryMethod.Network, new AsyncCallback(SendMessageCallback), result.AsyncState);
}
}
catch (Exception e) {
Complete(e, result);
}
GlobalLog.Leave("SmtpClient#" + ValidationHelper.HashString(this) + "::SendMailCallback");
}
void ConnectCallback(IAsyncResult result) {
GlobalLog.Enter("SmtpClient#" + ValidationHelper.HashString(this) + "::ConnectCallback");
try {
transport.EndGetConnection(result);
if (cancelled) {
Complete(null, result);
}
else {
transport.BeginSendMail(message.Sender != null ? message.Sender : message.From, recipients, message.BuildDeliveryStatusNotificationString(), new AsyncCallback(SendMailCallback), result.AsyncState);
}
}
catch (Exception e) {
Complete(e, result);
}
GlobalLog.Leave("SmtpClient#" + ValidationHelper.HashString(this) + "::ConnectCallback");
}
void GetConnection() {
if (!transport.IsConnected) {
transport.GetConnection(host, port);
}
}
void Abort() {
try {
transport.Abort();
}
catch {
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- NavigationPropertyEmitter.cs
- XmlDictionaryWriter.cs
- FileChangesMonitor.cs
- SrgsElementFactory.cs
- EnvelopedSignatureTransform.cs
- SelectionItemProviderWrapper.cs
- NegationPusher.cs
- NativeCppClassAttribute.cs
- MergeExecutor.cs
- Dictionary.cs
- ObjectDataSourceView.cs
- RemoteArgument.cs
- EntityContainerAssociationSet.cs
- ReadWriteObjectLock.cs
- RSAPKCS1SignatureFormatter.cs
- OdbcConnection.cs
- EventlogProvider.cs
- KeyPullup.cs
- XmlSigningNodeWriter.cs
- GridViewRowEventArgs.cs
- InputGestureCollection.cs
- RowUpdatedEventArgs.cs
- ColorConvertedBitmap.cs
- KnownColorTable.cs
- ToolStripProgressBar.cs
- PagedControl.cs
- UserNameSecurityTokenProvider.cs
- FileInfo.cs
- NavigationWindowAutomationPeer.cs
- IconBitmapDecoder.cs
- ParameterCollection.cs
- XsdValidatingReader.cs
- GetReadStreamResult.cs
- TouchEventArgs.cs
- PerformanceCounterPermissionAttribute.cs
- SimpleRecyclingCache.cs
- DesignerActionItemCollection.cs
- ProfileInfo.cs
- InstanceDataCollection.cs
- ParallelEnumerableWrapper.cs
- SecurityKeyUsage.cs
- BaseDataList.cs
- CachedPathData.cs
- WinFormsSpinner.cs
- Int16KeyFrameCollection.cs
- ReverseInheritProperty.cs
- LinearKeyFrames.cs
- DataColumnMapping.cs
- CharacterString.cs
- ScriptComponentDescriptor.cs
- WebConvert.cs
- KeyEvent.cs
- AvtEvent.cs
- ObjectViewFactory.cs
- TextDecorationUnitValidation.cs
- DataGridViewTopRowAccessibleObject.cs
- ReadOnlyMetadataCollection.cs
- DynamicPropertyReader.cs
- DrawingAttributes.cs
- BufferedReadStream.cs
- ColumnHeaderConverter.cs
- OdbcUtils.cs
- BaseCodePageEncoding.cs
- PropertyValueChangedEvent.cs
- CheckStoreFileValidityRequest.cs
- IBuiltInEvidence.cs
- Semaphore.cs
- ProviderBase.cs
- WorkflowDurableInstance.cs
- Hash.cs
- InternalTypeHelper.cs
- Propagator.cs
- QilChoice.cs
- ReadWriteControlDesigner.cs
- SmiEventSink_DeferedProcessing.cs
- TextContainerChangedEventArgs.cs
- DESCryptoServiceProvider.cs
- XmlValidatingReader.cs
- ColorComboBox.cs
- HttpHeaderCollection.cs
- XmlWriterTraceListener.cs
- OdbcDataReader.cs
- MsmqPoisonMessageException.cs
- SafeNativeMethods.cs
- CodeSnippetCompileUnit.cs
- HtmlInputRadioButton.cs
- SupportsEventValidationAttribute.cs
- PasswordRecovery.cs
- DeferredSelectedIndexReference.cs
- PlaceHolder.cs
- SHA256Managed.cs
- RMEnrollmentPage3.cs
- CorePropertiesFilter.cs
- CloseCryptoHandleRequest.cs
- SqlBulkCopy.cs
- ZoneLinkButton.cs
- UTF32Encoding.cs
- BaseContextMenu.cs
- RequestBringIntoViewEventArgs.cs
- NavigationWindow.cs