C#启动一个新的MailTo进程和HTML URL编码

时间:2020-12-27 20:40:11

I have created a new MailTo extension method for the Process class which just fills the Process with a new ProcessStartinfo which contains the required mailto arguments. I have created a method called FormatMailToArgument (Right at the end) which converts control characters to their Url Encoded equivelants and have tested this and it works but is there a better way of doing this?

我为Process类创建了一个新的MailTo扩展方法,它只是用一个包含所需mailto参数的新ProcessStartinfo填充Process。我已经创建了一个名为FormatMailToArgument的方法(最后在右边),它将控制字符转换为它们的Url编码等价物并测试了它并且它可以工作但是有更好的方法吗?

/// <summary>
/// <see cref="Process"/> extension methods.
/// </summary>
public static class Processes
{
    #region MailTo

    /// <summary>
    /// Populates the process with mailto <see cref="ProcessStartInfo"/>. You may leave any
    /// argument as <c>null</c> if not needed.
    /// </summary>
    /// <param name="process">The process.</param>
    /// <param name="mailMessage">The mail message.</param>
    public static void MailTo(this Process process, MailMessage mailMessage)
    {
        MailTo(
            process,
            mailMessage.To.ToDelimetedString(),
            mailMessage.CC.ToDelimetedString(),
            mailMessage.Bcc.ToDelimetedString(),
            mailMessage.Subject,
            mailMessage.Body);
    }

    /// <summary>
    /// Populates the process with mailto <see cref="ProcessStartInfo"/>. You may leave any
    /// argument as <c>null</c> if not needed.
    /// </summary>
    /// <param name="process">The process.</param>
    /// <param name="to">To email addresses.</param>
    public static void MailTo(this Process process, IEnumerable<string> to)
    {
        MailTo(
            process,
            to.ToDelimetedString(Character.SemiColon),
            null,
            null,
            null,
            null);
    }

    /// <summary>
    /// Populates the process with mailto <see cref="ProcessStartInfo"/>. You may leave any
    /// argument as <c>null</c> if not needed.
    /// </summary>
    /// <param name="process">The process.</param>
    /// <param name="to">To email addresses.</param>
    /// <param name="subject">The email subject.</param>
    public static void MailTo(this Process process, IEnumerable<string> to, string subject)
    {
        MailTo(
            process,
            to.ToDelimetedString(Character.SemiColon),
            null,
            null,
            subject,
            null);
    }

    /// <summary>
    /// Populates the process with mailto <see cref="ProcessStartInfo"/>. You may leave any
    /// argument as <c>null</c> if not needed.
    /// </summary>
    /// <param name="process">The process.</param>
    /// <param name="to">To email addresses.</param>
    /// <param name="subject">The email subject.</param>
    /// <param name="body">The email body.</param>
    public static void MailTo(
        this Process process,
        IEnumerable<string> to,
        string subject,
        string body)
    {
        MailTo(
            process,
            to.ToDelimetedString(Character.SemiColon),
            null,
            null,
            subject,
            body);
    }

    /// <summary>
    /// Populates the process with mailto <see cref="ProcessStartInfo"/>. You may leave any
    /// argument as <c>null</c> if not needed.
    /// </summary>
    /// <param name="process">The process.</param>
    /// <param name="to">To email addresses.</param>
    /// <param name="cc">The Cc email addresses.</param>
    /// <param name="subject">The email subject.</param>
    /// <param name="body">The email body.</param>
    public static void MailTo(
        this Process process,
        IEnumerable<string> to,
        IEnumerable<string> cc,
        string subject,
        string body)
    {
        MailTo(
            process,
            to.ToDelimetedString(Character.SemiColon),
            cc.ToDelimetedString(Character.SemiColon),
            null,
            subject,
            body);
    }

    /// <summary>
    /// Populates the process with mailto <see cref="ProcessStartInfo"/>. You may leave any 
    /// argument as <c>null</c> if not needed.
    /// </summary>
    /// <param name="process">The process.</param>
    /// <param name="to">To email addresses.</param>
    /// <param name="cc">The Cc email addresses.</param>
    /// <param name="bcc">The Bcc email addresses.</param>
    /// <param name="subject">The email subject.</param>
    /// <param name="body">The email body.</param>
    public static void MailTo(
        this Process process,
        IEnumerable<string> to,
        IEnumerable<string> cc,
        IEnumerable<string> bcc,
        string subject,
        string body)
    {
        MailTo(
            process,
            (to == null) ? null : to.ToDelimetedString(Character.SemiColon),
            (cc == null) ? null : cc.ToDelimetedString(Character.SemiColon),
            (bcc == null) ? null : bcc.ToDelimetedString(Character.SemiColon),
            subject,
            body);
    }

    /// <summary>
    /// Populates the process with mailto <see cref="ProcessStartInfo"/>. You may leave any
    /// argument as <c>null</c> if not needed.
    /// </summary>
    /// <param name="process">The process.</param>
    /// <param name="to">To email addresses.</param>
    /// <param name="cc">The Cc email addresses.</param>
    /// <param name="bcc">The Bcc email addresses.</param>
    /// <param name="subject">The email subject.</param>
    /// <param name="body">The email body.</param>
    /// <param name="attachmentPath">The attachment file path.</param>
    public static void MailTo(
        this Process process,
        IEnumerable<string> to,
        IEnumerable<string> cc,
        IEnumerable<string> bcc,
        string subject,
        string body,
        string attachmentPath)
    {
        MailTo(
            process,
            (to == null) ? null : to.ToDelimetedString(Character.SemiColon),
            (cc == null) ? null : cc.ToDelimetedString(Character.SemiColon),
            (bcc == null) ? null : bcc.ToDelimetedString(Character.SemiColon),
            subject,
            body,
            attachmentPath);
    }

    /// <summary>
    /// Populates the process with mailto <see cref="ProcessStartInfo"/>. You may leave any 
    /// argument as <c>null</c> if not needed.
    /// </summary>
    /// <param name="process">The process.</param>
    /// <param name="to">To email addresses delimeted by a semi-colon.</param>
    /// <param name="cc">The Cc email addresses delimeted by a semi-colon.</param>
    /// <param name="bcc">The Bcc email addresses delimeted by a semi-colon.</param>
    /// <param name="subject">The email subject.</param>
    /// <param name="body">The email body.</param>
    public static void MailTo(this Process process, string to, string cc, string bcc, string subject, string body)
    {
        MailTo(process, to, cc, bcc, subject, body, null);
    }

    /// <summary>
    /// Populates the process with mailto <see cref="ProcessStartInfo"/>. You may leave any
    /// argument as <c>null</c> if not needed.
    /// </summary>
    /// <param name="process">The process.</param>
    /// <param name="to">To email addresses delimeted by a semi-colon.</param>
    /// <param name="cc">The Cc email addresses delimeted by a semi-colon.</param>
    /// <param name="bcc">The Bcc email addresses delimeted by a semi-colon.</param>
    /// <param name="subject">The email subject.</param>
    /// <param name="body">The email body.</param>
    /// <param name="attachmentPath">The attachment file path. Note: this will not work in some 
    /// email applications.</param>
    public static void MailTo(
        this Process process,
        string to,
        string cc,
        string bcc,
        string subject,
        string body,
        string attachmentPath)
    {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.Append(Uri.UriSchemeMailto + Character.Colon);
        stringBuilder.Append(FormatMailToArgument(to));

        if (!string.IsNullOrEmpty(cc) || !string.IsNullOrEmpty(bcc) ||
            !string.IsNullOrEmpty(subject) || !string.IsNullOrEmpty(body) ||
            !string.IsNullOrEmpty(attachmentPath))
        {
            stringBuilder.Append(Character.Question);

            List<string> arguments = new List<string>();

            if (!string.IsNullOrEmpty(subject))
            {
                arguments.Add("subject=" + FormatMailToArgument(subject));
            }

            if (!string.IsNullOrEmpty(body))
            {
                arguments.Add("body=" + FormatMailToArgument(body));
            }

            if (!string.IsNullOrEmpty(cc))
            {
                arguments.Add("CC=" + FormatMailToArgument(cc));
            }

            if (!string.IsNullOrEmpty(bcc))
            {
                arguments.Add("BCC=" + FormatMailToArgument(bcc));
            }

            if (!string.IsNullOrEmpty(attachmentPath))
            {
                arguments.Add("attachment=" + FormatMailToArgument(attachmentPath));
            }

            stringBuilder.Append(arguments.ToDelimetedString(Character.Ampersand));
        }

        process.StartInfo = new ProcessStartInfo(stringBuilder.ToString());
    }

    #endregion

    #region Methods

    /// <summary>
    /// Formats the mailto argument. Converts <![CDATA['%', '&', ' ', '?', '\t', '\n']]> to their 
    /// hexadecimal representation.
    /// </summary>
    /// <param name="argument">The argument.</param>
    /// <returns>The formatted argument.</returns>
    private static string FormatMailToArgument(string argument)
    {
        return argument.
            Replace(Character.Percent.ToString(), "%25").
            Replace(Character.Ampersand.ToString(), "%26").
            Replace(Character.Colon.ToString(), "%3A").
            Replace(Character.HorizontalTab.ToString(), "%0D").
            Replace(Character.NewLine.ToString(), "%0A").
            Replace(Character.Question.ToString(), "%3F").
            Replace(Character.Quote.ToString(), "%22").
            Replace(Character.Space.ToString(), "%20");
    }

    #endregion
}

2 个解决方案

#1


If you mean is there are more efficient way to escape your email addresses then yes you could use the System.Uri class.

如果您的意思是有更有效的方法来转义您的电子邮件地址,那么您可以使用System.Uri类。

string escapedAddress = Uri.EscapeUriString("mailto:joe blogg's\r\n@mail.com");
Console.WriteLine(escapedAddress);

Output:

mailto:joe%20blogg's%0D%0A@mail.com

You'll notice in my example the single quote character doesn't get escaped but that's because it's not required to be in email addresses.

你会注意到我的例子中单引号字符没有被转义,但这是因为它不需要在电子邮件地址中。

As far as the general approach you have used I don't see why you would add an extension method to the Process class. To send an email and have all the address escaping. attachments, server authentication etc. etc. taken care of why not just use the System.Net.Mail classes?

就您使用的一般方法而言,我不明白为什么要向Process类添加扩展方法。发送电子邮件并让所有地址都逃脱。附件,服务器身份验证等等。照顾为什么不只是使用System.Net.Mail类?

#2


As documented in is this official link, the EscapeUriString method assumes that stringToEscape parameter has no escape sequences in it.

如此官方链接中所述,EscapeUriString方法假定stringToEscape参数中没有转义序列。

This method is perfect for escaping Uris, but be careful because the target string is a mailto: line that can contain many parameters (not only subject, body, ...), obviously separated each one with some escape characters...like & and ?.

这个方法非常适合转义Uris,但要小心,因为目标字符串是一个mailto:行,它可以包含许多参数(不仅是主题,正文,...),显然每个参数都有一些转义字符...就像&和?

So, in my tests with Windows Store Apps with text taken from @anon comment, that string will not be fully escaped using just Uri.EscapeUriString() method, because it contains the escape sequence &.

因此,在我的Windows Store应用程序测试中,文本取自@anon注释,该字符串不会仅使用Uri.EscapeUriString()方法完全转义,因为它包含转义序列&。

You will need an extra manual escape to get the whole string be passed as parameter in a mailto: Uri:

你将需要一个额外的手动转义来将整个字符串作为参数传递到mailto:Uri:

Uri.EscapeUriString(stringToEscape).Replace("&", "%26");

#1


If you mean is there are more efficient way to escape your email addresses then yes you could use the System.Uri class.

如果您的意思是有更有效的方法来转义您的电子邮件地址,那么您可以使用System.Uri类。

string escapedAddress = Uri.EscapeUriString("mailto:joe blogg's\r\n@mail.com");
Console.WriteLine(escapedAddress);

Output:

mailto:joe%20blogg's%0D%0A@mail.com

You'll notice in my example the single quote character doesn't get escaped but that's because it's not required to be in email addresses.

你会注意到我的例子中单引号字符没有被转义,但这是因为它不需要在电子邮件地址中。

As far as the general approach you have used I don't see why you would add an extension method to the Process class. To send an email and have all the address escaping. attachments, server authentication etc. etc. taken care of why not just use the System.Net.Mail classes?

就您使用的一般方法而言,我不明白为什么要向Process类添加扩展方法。发送电子邮件并让所有地址都逃脱。附件,服务器身份验证等等。照顾为什么不只是使用System.Net.Mail类?

#2


As documented in is this official link, the EscapeUriString method assumes that stringToEscape parameter has no escape sequences in it.

如此官方链接中所述,EscapeUriString方法假定stringToEscape参数中没有转义序列。

This method is perfect for escaping Uris, but be careful because the target string is a mailto: line that can contain many parameters (not only subject, body, ...), obviously separated each one with some escape characters...like & and ?.

这个方法非常适合转义Uris,但要小心,因为目标字符串是一个mailto:行,它可以包含许多参数(不仅是主题,正文,...),显然每个参数都有一些转义字符...就像&和?

So, in my tests with Windows Store Apps with text taken from @anon comment, that string will not be fully escaped using just Uri.EscapeUriString() method, because it contains the escape sequence &.

因此,在我的Windows Store应用程序测试中,文本取自@anon注释,该字符串不会仅使用Uri.EscapeUriString()方法完全转义,因为它包含转义序列&。

You will need an extra manual escape to get the whole string be passed as parameter in a mailto: Uri:

你将需要一个额外的手动转义来将整个字符串作为参数传递到mailto:Uri:

Uri.EscapeUriString(stringToEscape).Replace("&", "%26");