C# - 應用App.config實作寄發EMail的MailUtility

寄發EMail是許多系統常用必備的功能,.Net也有提供EMail相關操作的Class與Sample Code,所以要實作寄送EMail的功能是非常簡單的,要如何提高重覆使用性與彈性才是重點。

針對重覆使用性,限量決定將Mail功能抽出來成為一個Utility,使用時只要簡單的呼叫MailUtility的方法就可以直接使用;針對設定的彈性上,限量決定與前先日子練習的自訂App.config結合,讓一些EMail相關的基本設定可以在App.config裡進行更改,下面就讓我們來看看細節如何實作:

MailConfigSection.cs : 定義App.config裡Mail Section裡對應的屬性


using System;
using System.Configuration;

namespace SendMailTest
{
 public class MailConfigSection : ConfigurationSection
 {
  [ConfigurationProperty( "ServerInfo" )]
  public MailElement MailSettings
  {
   get { return (MailElement)this["ServerInfo"]; }
  }
 }

 public class MailElement : GenericElement
 {
  public override Object ElementKey
  {
   get { return this.Sender; }
  }

  [ConfigurationProperty( "ServerAddress" )]
  public String ServerAddress { get { return this["ServerAddress"].ToString(); } }

  [ConfigurationProperty( "Sender" )]
  public String Sender { get { return this["Sender"].ToString(); } }

  [ConfigurationProperty( "Password" )]
  public String Password { get { return this["Password"].ToString(); } }

  [ConfigurationProperty( "SenderName" )]
  public String SenderName { get { return this["SenderName"].ToString(); } }
 }
}

MailConfigSection是為了讓程式可以識別我們在App.config裡所定義的自訂section(在 App.config自訂section程式碼架構 這篇文章中有簡單的教大家如何使用),這裡限量定義了幾個Mail可能用到的一些屬性,像ServerAddress(SMTP Server位址,例如GMail, HotMail...等), Sender(寄件者EMail位址帳號), Password(寄件者EMail密碼), SenderName(寄件者名稱)。

MailUtility.cs : 提供EMail相關功能

using System;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Configuration;

namespace SendMailTest
{
 public static class MailUtility
 {
  #region Mail基本資訊
  private static readonly String SMTP_ADDRESS;
  private static readonly String PASSWORD;
  private static readonly String SENDER_ADDRESS;
  private static readonly String SENDER_NAME;
  private const Int32 PORT = 1104;
  private const Boolean ENABLE_SSL = true;
  #endregion

  static MailUtility()
  {
   try
   {
    var section = ConfigurationManager.GetSection( "Custom/Mail" ) as MailConfigSection;
    var mailSetting = section.MailSettings;
    SMTP_ADDRESS = mailSetting.ServerAddress;
    SENDER_ADDRESS = mailSetting.Sender;
    PASSWORD = mailSetting.Password;
    SENDER_NAME = mailSetting.SenderName;
   } catch(Exception ex) {
    throw ex;
   }
  }

  public static Boolean SendMail( String[] receivers, String subject, String content )
  {
   return SendMail( receivers, subject, content, String.Empty );
  }

  public static Boolean SendMail( String[] receivers, String subject, String content, String file )
  {
   Boolean status = true;
   try
   {
    using ( MailMessage mail = new MailMessage() )
    {
     mail.From = new MailAddress( SENDER_ADDRESS, SENDER_NAME );
     receivers.ToList().ForEach( e => mail.To.Add( e ) );
     mail.Subject = subject;
     if ( file != String.Empty )
     {
      Attachment attachFile = new Attachment( file );
      mail.Attachments.Add( attachFile );
     }
     mail.Body = content;
     mail.IsBodyHtml = true;

     using ( SmtpClient smtp = new SmtpClient( SMTP_ADDRESS, PORT ) )
     {
      smtp.Credentials = new NetworkCredential( SENDER_ADDRESS, PASSWORD );
      smtp.EnableSsl = ENABLE_SSL;
      smtp.Send( mail );
     }
    }
   }
   catch ( Exception ex )
   {
    status = false;
   }

   return status;
  }
 }
}

MailUtility因為限量覺得單純只提供Mail相關功能,所以就把它實作成static class,一些從App.config讀取的資訊限制不能改變,所以宣告成static readonly與const的類型,在靜態建構子裡就從App.config裡取出相關資訊,當然,如果再取出的途中發生錯誤就會直接丟出錯誤。這裡提供兩種SendMail的多載,傳入收件者EMail位址陣, 信件主旨與內容,其實呼叫的都是同一個,只是差別在是否要傳送檔案,如果傳送成功就回傳true,反之傳送發生錯誤會回傳false。

App.config : 設置EMail基本資訊(STMP Server位置, 寄件者...)



<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <configSections>
  <sectionGroup name="Custom">
   <section name="Mail" type="SendMailTest.MailConfigSection, SendMailTest" />
  </sectionGroup>
 </configSections>

 <!--設置SMTP Server位置與發送者的帳密-->
 <!--ServerAddress為Mail Server 位址,Sender為發送者帳號,Password為發送者密碼-->
 <Custom>
  <Mail>
   <ServerInfo ServerAddress="smtp.gmail.com" Sender="XXX@gmail.com" Password="xxxxxx" SenderName="限量"></ServerInfo>
  </Mail>
 </Custom>
 <!--設置SMTP Server位置與發送者的帳密-->

 <startup>
  <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
 </startup>
</configuration>

App.config可以自訂設置Mail的基本資訊,在這特別的是sectionGroup,這和之前提到的自訂App.config那篇有點不一樣,這裡就來簡單的說一下,使用sectionGroup,顧名思義,就是section的group,在上面可以看到Custom Region裡有Mail Section,因為Custom Region是sectionGroup,所以可以在裡面放其他的section。

Program.cs : 主程式


using System;

namespace SendMailTest
{
 class Program
 {
  static void Main( string[] args )
  {
   var msg = MailUtility.SendMail( new[] { "XXXX@hotmail.com", "XXXX@gmail.com" }, "測試Mail", "這是封測試郵件" )
    ? "發送成功" : "發送失敗";
   Console.WriteLine(msg);

   Console.Read();
  }
 }
}


這MailUtility算是個小試身手的小程式,未考慮到其他情況,例如寄件, 讀取...等,這些其他功能也許會使這個MailUtility的架構改變,這就要看個人的設計想法囉。




留言