mirror of
https://github.com/aphrody-labs/PowerShell.git
synced 2026-10-17 20:56:02 +00:00
526 lines
17 KiB
C#
526 lines
17 KiB
C#
/********************************************************************++
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
--********************************************************************/
|
|
|
|
using System;
|
|
using System.Text;
|
|
using System.Globalization;
|
|
using System.Net.Mail;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Management.Automation;
|
|
|
|
|
|
namespace Microsoft.PowerShell.Commands
|
|
{
|
|
#region SendMailMessage
|
|
/// <summary>
|
|
/// implementation for the Send-MailMessage command
|
|
/// </summary>
|
|
[Cmdlet(VerbsCommunications.Send, "MailMessage", HelpUri = "https://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 the server. <see cref="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 recipient 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
|
|
} |