PowerShell/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Send-MailMessage.cs
PowerShell Team c748652c34 Copy all mapped files from [SD:725290]
commit 8cec8f150da7583b7af5efbe2853efee0179750c
2016-07-28 23:23:03 -07:00

551 lines
18 KiB
C#

/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Collections;
using System.Globalization;
using System.Net.Mail;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Management.Automation;
using System.Management.Automation.Internal;
using Microsoft.PowerShell.Commands.Internal.Format;
namespace Microsoft.PowerShell.Commands
{
#region SendMailMessage
/// <summary>
/// implementation for the Send-MailMessage command
/// </summary>
[Cmdlet(VerbsCommunications.Send, "MailMessage", HelpUri = "http://go.microsoft.com/fwlink/?LinkID=135256")]
public sealed class SendMailMessage : PSCmdlet
{
#region Command Line Parameters
/// <summary>
/// Specifies the files names to be attached to the email.
/// If the filename specified can not be found, then the relevant error
/// message should be thrown.
/// </summary>
[Parameter(ValueFromPipeline = true)]
[ValidateNotNullOrEmpty]
[Alias("PsPath")]
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
public String[] Attachments
{
get { return attachments; }
set
{
attachments = value;
}
}
private String[] attachments;
/// <summary>
/// Specifies the address collection that contains the
/// blind carbon copy (BCC) recipients for the e-mail message.
/// </summary>
[Parameter]
[ValidateNotNullOrEmpty]
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
public String[] Bcc
{
get { return bcc; }
set
{
bcc = value;
}
}
private String[] bcc;
/// <summary>
/// Specifies the body (content) of the message
/// </summary>
[Parameter(Position = 2)]
[ValidateNotNullOrEmpty]
public String Body
{
get { return body; }
set
{
body = value;
}
}
private String body;
/// <summary>
/// Specifies a value indicating whether the mail message body is in Html.
/// </summary>
[Parameter]
[Alias("BAH")]
public SwitchParameter BodyAsHtml
{
get { return bodyashtml; }
set
{
bodyashtml = value;
}
}
private SwitchParameter bodyashtml;
/// <summary>
/// Specifies the encoding used for the content of the body and also the subject.
/// </summary>
[Parameter()]
[Alias("BE")]
[ValidateNotNullOrEmpty]
[ArgumentToEncodingNameTransformationAttribute()]
public Encoding Encoding
{
get { return encoding; }
set
{
encoding = value;
}
}
private Encoding encoding = new ASCIIEncoding();
/// <summary>
/// Specifies the address collection that contains the
/// carbon copy (CC) recipients for the e-mail message.
/// </summary>
[Parameter]
[ValidateNotNullOrEmpty]
[SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Cc")]
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
public String[] Cc
{
get { return cc; }
set
{
cc = value;
}
}
private String[] cc;
/// <summary>
/// Specifies the delivery notifications options for the e-mail message. The various
/// option available for this parameter are None, OnSuccess, OnFailure, Delay and Never
/// </summary>
[Parameter()]
[Alias("DNO")]
[ValidateNotNullOrEmpty]
public DeliveryNotificationOptions DeliveryNotificationOption
{
get { return deliverynotification; }
set
{
deliverynotification = value;
}
}
private DeliveryNotificationOptions deliverynotification;
/// <summary>
/// Specifies the from address for this e-mail message. The default value for
/// this parameter is the email address of the currently logged on user
/// </summary>
[Parameter(Mandatory = true)]
[ValidateNotNullOrEmpty]
public String From
{
get { return from; }
set
{
from = value;
}
}
private String from;
/// <summary>
/// Specifies the name of the Host used to send the email. This host name will be assigned
/// to the Powershell variable PSEmailServer,if this host can not reached an appropriate error
/// message will be displayed.
/// </summary>
[Parameter(Position = 3)]
[Alias("ComputerName")]
[ValidateNotNullOrEmpty]
public String SmtpServer
{
get { return smtpserver; }
set
{
smtpserver = value;
}
}
private String smtpserver;
/// <summary>
/// Specifies the priority of the email message. The valid values for this are Normal, High and Low
/// </summary>
[Parameter]
[ValidateNotNullOrEmpty]
public MailPriority Priority
{
get { return priority; }
set
{
priority = value;
}
}
private MailPriority priority;
/// <summary>
/// Specifies the subject of the email message.
/// </summary>
[Parameter(Mandatory = true, Position = 1)]
[Alias("sub")]
[ValidateNotNullOrEmpty]
public String Subject
{
get { return subject; }
set
{
subject = value;
}
}
private String subject;
/// <summary>
/// Specifies the To address for this e-mail message.
/// </summary>
[Parameter(Mandatory = true, Position = 0)]
[ValidateNotNullOrEmpty]
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
public String[] To
{
get { return to; }
set
{
to = value;
}
}
private String[] to;
/// <summary>
/// Specifies the credential for this e-mail message.
/// </summary>
[Parameter()]
[Credential]
[ValidateNotNullOrEmpty]
public PSCredential Credential
{
get { return credential; }
set
{
credential = value;
}
}
private PSCredential credential;
/// <summary>
/// Specifies if Secured layer is required or not
/// </summary>
[Parameter()]
public SwitchParameter UseSsl
{
get { return usessl; }
set
{
usessl = value;
}
}
private SwitchParameter usessl;
/// <summary>
/// Specifies the Port to be used on <paramref name="SmtpServer"/>
/// </summary>
/// <remarks>
/// Value must be greater than zero.
/// </remarks>
[Parameter()]
[ValidateRange(0, Int32.MaxValue)]
public int Port
{
get { return port; }
set { port = value; }
}
private int port = 0;
#endregion
#region private variables and methods
// Instantiate a new instance of MailMessage
private MailMessage mMailMessage = new MailMessage();
private SmtpClient mSmtpClient = null;
/// <summary>
/// Add the input addresses which are either string or hashtable to the MailMessage
/// It returns true if the from parameter has more than one value
/// </summary>
/// <param name="address"></param>
/// <param name="param"></param>
/// <returns></returns>
private void AddAddressesToMailMessage(object address, string param)
{
string[] objEmailAddresses = address as string[];
foreach (string strEmailAddress in objEmailAddresses)
{
try
{
switch (param)
{
case "to":
{
mMailMessage.To.Add(new MailAddress(strEmailAddress));
break;
}
case "cc":
{
mMailMessage.CC.Add(new MailAddress(strEmailAddress));
break;
}
case "bcc":
{
mMailMessage.Bcc.Add(new MailAddress(strEmailAddress));
break;
}
}
}
catch (FormatException e)
{
ErrorRecord er = new ErrorRecord(e, "FormatException", ErrorCategory.InvalidType, null);
WriteError(er);
continue;
}
}
}
#endregion
#region Overrides
/// <summary>
/// ProcessRecord override
/// </summary>
protected override
void
BeginProcessing()
{
try
{
// Set the sender address of the mail message
mMailMessage.From = new MailAddress(from);
}
catch (FormatException e)
{
ErrorRecord er = new ErrorRecord(e, "FormatException", ErrorCategory.InvalidType, from);
ThrowTerminatingError(er);
// return;
}
// Set the recepient address of the mail message
AddAddressesToMailMessage(to, "to");
// Set the BCC address of the mail message
if (bcc != null)
{
AddAddressesToMailMessage(bcc, "bcc");
}
// Set the CC address of the mail message
if (cc != null)
{
AddAddressesToMailMessage(cc, "cc");
}
//set the delivery notification
mMailMessage.DeliveryNotificationOptions = deliverynotification;
// Set the subject of the mail message
mMailMessage.Subject = subject;
// Set the body of the mail message
mMailMessage.Body = body;
//set the subject and body encoding
mMailMessage.SubjectEncoding = encoding;
mMailMessage.BodyEncoding = encoding;
// Set the format of the mail message body as HTML
mMailMessage.IsBodyHtml = bodyashtml;
// Set the priority of the mail message to normal
mMailMessage.Priority = priority;
//get the PowerShell environment variable
//globalEmailServer might be null if it is deleted by: PS> del variable:PSEmailServer
PSVariable globalEmailServer = SessionState.Internal.GetVariable(SpecialVariables.PSEmailServer);
if (smtpserver == null && globalEmailServer != null)
{
smtpserver = Convert.ToString(globalEmailServer.Value, CultureInfo.InvariantCulture);
}
if (string.IsNullOrEmpty(smtpserver))
{
ErrorRecord er = new ErrorRecord(new InvalidOperationException(SendMailMessageStrings.HostNameValue), null, ErrorCategory.InvalidArgument, null);
this.ThrowTerminatingError(er);
}
if (0 == port)
{
mSmtpClient = new SmtpClient(smtpserver);
}
else
{
mSmtpClient = new SmtpClient(smtpserver, port);
}
if (usessl)
{
mSmtpClient.EnableSsl = true;
}
if (credential != null)
{
mSmtpClient.UseDefaultCredentials = false;
mSmtpClient.Credentials = credential.GetNetworkCredential();
}
else if (!usessl)
{
mSmtpClient.UseDefaultCredentials = true;
}
}
/// <summary>
/// ProcessRecord override
/// </summary>
protected override void ProcessRecord()
{
//add the attachments
if (attachments != null)
{
string filepath = string.Empty;
foreach (string attachFile in attachments)
{
try
{
filepath = PathUtils.ResolveFilePath(attachFile, this);
}
catch (ItemNotFoundException e)
{
//NOTE: This will throw
PathUtils.ReportFileOpenFailure(this, filepath, e);
}
Attachment mailAttachment = new Attachment(filepath);
mMailMessage.Attachments.Add(mailAttachment);
}
}
}
/// <summary>
/// EndProcessing
/// </summary>
protected override void EndProcessing()
{
try
{
// Send the mail message
mSmtpClient.Send(mMailMessage);
}
catch (SmtpFailedRecipientsException ex)
{
ErrorRecord er = new ErrorRecord(ex, "SmtpFailedRecipientsException", ErrorCategory.InvalidOperation, mSmtpClient);
WriteError(er);
}
catch (SmtpException ex)
{
if (ex.InnerException != null)
{
ErrorRecord er = new ErrorRecord(new SmtpException(ex.InnerException.Message), "SmtpException", ErrorCategory.InvalidOperation, mSmtpClient);
WriteError(er);
}
else
{
ErrorRecord er = new ErrorRecord(ex, "SmtpException", ErrorCategory.InvalidOperation, mSmtpClient);
WriteError(er);
}
}
catch (InvalidOperationException ex)
{
ErrorRecord er = new ErrorRecord(ex, "InvalidOperationException", ErrorCategory.InvalidOperation, mSmtpClient);
WriteError(er);
}
catch (System.Security.Authentication.AuthenticationException ex)
{
ErrorRecord er = new ErrorRecord(ex, "AuthenticationException", ErrorCategory.InvalidOperation, mSmtpClient);
WriteError(er);
}
//if we don't dispose the attachments, the sender can't modify or use the files sent.
mMailMessage.Attachments.Dispose();
}
#endregion
}
/// <summary>
/// To make it easier to specify -Encoding parameter, we add an ArgumentTransformationAttribute here.
/// When the input data is of type string and is valid to be converted to System.Text.Encoding, we do
/// the conversion and return the converted value. Otherwise, we just return the input data.
/// </summary>
internal sealed class ArgumentToEncodingNameTransformationAttribute : ArgumentTransformationAttribute
{
public override object Transform(EngineIntrinsics engineIntrinsics, object inputData)
{
string encodingName;
if (LanguagePrimitives.TryConvertTo<string>(inputData, out encodingName))
{
if (string.Equals(encodingName, EncodingConversion.Unknown, StringComparison.OrdinalIgnoreCase) ||
string.Equals(encodingName, EncodingConversion.String, StringComparison.OrdinalIgnoreCase) ||
string.Equals(encodingName, EncodingConversion.Unicode, StringComparison.OrdinalIgnoreCase) ||
string.Equals(encodingName, EncodingConversion.BigEndianUnicode, StringComparison.OrdinalIgnoreCase) ||
string.Equals(encodingName, EncodingConversion.Utf8, StringComparison.OrdinalIgnoreCase) ||
string.Equals(encodingName, EncodingConversion.Utf7, StringComparison.OrdinalIgnoreCase) ||
string.Equals(encodingName, EncodingConversion.Utf32, StringComparison.OrdinalIgnoreCase) ||
string.Equals(encodingName, EncodingConversion.Ascii, StringComparison.OrdinalIgnoreCase) ||
string.Equals(encodingName, EncodingConversion.Default, StringComparison.OrdinalIgnoreCase) ||
string.Equals(encodingName, EncodingConversion.OEM, StringComparison.OrdinalIgnoreCase))
{
// the encodingName is guaranteed to be valid, so it is safe to pass null to method
// Convert(Cmdlet cmdlet, string encoding) as the value of 'cmdlet'.
return EncodingConversion.Convert(null, encodingName);
}
}
return inputData;
}
}
#endregion
}