星期四, 5月 10, 2007

[.Net]利用 Gmail SMTP server 來寄信

詳情可以參考這篇:Send E-Mail from your .NET application using your GMail Account,內文提供了 .Net 1.1/2.0 的方法。

我自己用 .Net 2,試的結果,發現有這個錯誤訊息出現:"Must issue a STARTTLS command first"
Google 大神告訴我,有蠻多人詢問這個問題
仔細研讀之後,發現是我自己忘了幫 SmtpClient 設置 EnableSsl 屬性為 true。

加上之後,又丟出 "The requested feature is not implemented."。
咦?沒實做,難道我用的Mono 1.2.3.1還沒實做這部份?
Reflector反組譯出來看之後,果然...真的還沒實做 SSL 傳輸的部份。
希望下一版會加進去...這樣就還是可以Linux 下跑。
以下是程式碼,它是一個命令列的程式,讓你可以指定必要的欄位後寄送郵件。打 MailSharp -h 可以得到使用說明。
/**
* MailSharp
*
* Reference:
* Send E-Mail from your .NET application using your GMail Account - The Code Project - C# Programming <http://www.codeproject.com/useritems/SendMailUsingGmailAccount.asp>
*/
using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Net.Mime;
using System.Threading;
using System.ComponentModel;

namespace MailSharp {
public class MailSharpConsole {
public static string showUsage() {
StringBuilder sb = new StringBuilder();

sb.AppendLine( "Usage: MailSharp [options] ToAddress" );
sb.AppendLine( "\t-a File to attach." );
sb.AppendLine( "\t-f From address" );
sb.AppendLine( "\t-b Body message" );
sb.AppendLine( "\t-s Subject");
sb.AppendLine( "\t-S SMTP server host" );
sb.AppendLine( "\t-U Username for SMTP server authentication" );
sb.AppendLine( "\t-p Password for SMTP server authentication" );
sb.AppendLine( "\t-l Use SSL" );
sb.AppendLine( "\t-h Help/Usage");
sb.AppendLine();
sb.AppendLine( "Example:" );
sb.AppendLine( "\tFor GMail" );
sb.AppendLine( "\tMailSharp -f your_name@gmail.com -b Test -s Test -S smtp.gmail.com -P 587 -l -U your_gmail -p your_gmail_password someone@somewhere.com" );

return sb.ToString();
}

public static void Main(string[] args) {
MailAddress from = null;
MailAddress to = null;
MailMessage message = new MailMessage();
SmtpClient client = new SmtpClient();
NetworkCredential myCred = new NetworkCredential();
bool bShowUsage=false;

try {
if ( args.Length > 0 ) {
for ( int i=0; i<args.Length; i++ ) {
switch ( args[i] ) {
case "-S": // server host
i++;
if ( i<args.Length ) {
client.Host = args[i];
} else
throw new Exception( "-S was specified, but no value." );
break;
case "-P": // server port
i++;
if ( i<args.Length ) {
client.Port=Convert.ToInt32( args[i] );
} else
throw new Exception( "-P was specified, but no value." );
break;
case "-T": // timeout
i++;
if ( i<args.Length ) {
client.Timeout = Convert.ToInt32( args[i] );
} else
throw new Exception( "-T was specified, but no value." );
break;
case "-U": // username for smtp server authentication
i++;
if ( i<args.Length )
myCred.UserName = args[i];
else
throw new Exception( "-U was specified, but no value." );
break;
case "-p": // password for smtp server authentication
i++;
if ( i<args.Length )
myCred.Password = args[i];
else
throw new Exception( "-p was specified, but no value." );
break;
case "-l": // use SSL
client.EnableSsl = true;
break;
case "-s": // subject
i++; // next one is subject.
if ( i<args.Length ) {
message.Subject = args[i];
message.SubjectEncoding = System.Text.Encoding.UTF8;
} else
throw new Exception( "-s was specified, but no value." );
break;
case "-a": // attachment
i++; // next one is attachment filename.
if ( i<args.Length ) {
// Add attachment.
Attachment data = new Attachment( args[i], MediaTypeNames.Application.Octet);
message.Attachments.Add(data);
} else
throw new Exception( "-a was specified, but no value." );
break;
case "-b": // body message.
i++; // next one is body message
if ( i<args.Length ) {
message.Body = args[i];
message.BodyEncoding = System.Text.Encoding.UTF8;
} else
throw new Exception( "-b was specified, but no value." );
break;
case "-f": // from address
i++;
if ( i<args.Length ) {
// Specify the e-mail sender.
// Create a mailing address that includes a UTF8 character
// in the display name.
// from = new MailAddress( "someone@gmail.com", "someone", System.Text.Encoding.UTF8);
from = new MailAddress( args[i] );
} else
throw new Exception( "-f was specified, but no value." );
break;
case "-h": // show help/usage
bShowUsage=true;
break;
default:
to = new MailAddress( args[i] );
break;
}
}
} else
throw new Exception("No arguments.");
} catch ( Exception ex ) {
Console.WriteLine( ex.Message );
bShowUsage = true;
}

try {
if ( bShowUsage == true )
throw new Exception( showUsage() );

if ( from==null )
throw new Exception( "Must specify from address (-f)." );

// Set destinations for the e-mail message.
if ( to == null )
throw new Exception("At least, must specify to address");

if ( client.Host == string.Empty )
throw new Exception("Must specify SMTP Server (-S)." );

// Specify the message content.
message.From = from;
message.To.Add( to );

// Credentials are necessary if the server requires the client
// to authenticate before it will send e-mail on the client's behalf.
//client.UseDefaultCredentials = false;
client.Credentials = myCred;

// Send.
// If you need asynchronous sample, please visit the reference above.
client.Send(message);

Console.WriteLine("Done.");
} catch ( Exception ex ) {
Console.WriteLine( "Exception was raised when sending...");
Console.WriteLine( ex.Message );
} finally {
// Clean up.
message.Dispose();
}
}
}
}

如果你打算在 Linux 下服用的話,可以搭配這個 script,免去你每次前面都要打 mono 的麻煩。
#!/bin/sh
exec /usr/bin/mono $MONO_OPTIONS "MailSharp.exe" "$@"

沒有留言: