用單一function讓PHP登入SMTP Server寄信

PHP內建的mail()功能比較陽春,雖然能夠透過ini_set()來指定SMTP Server,但是只能支援不需登入的那種模式。如果需要用指定的SMTP Server,即不想或是不能用Gmail的話(appleboy建議我用libcurl還給了我一個連結,不過我沒細看)PHP官網上有很多前輩們的討論和貢獻(這個功能的討論大多是在Function Reference的Mail Functions底下,而不是mail()的頁面)。
以下的code是我從Rob的文章裡面稍作修改的(附帶一提,前面那個聯結交大的鏡像站,詭異的是PHP本站的那一篇居然沒有色碼變色!!??),搜尋一下$param就知道可以設定哪些東西了(至於哪些是一定要設定的就請自行判斷吧)
function authMail( $param ) {
/* your configuration here */
$port = isset( $param['port'] ) ? $param['port'] : 25;
$timeout = isset( $param['timeout'] ) ? $param['timeout'] : 30;
$charset = isset( $param['charset'] ) ? $param['charset'] : 'iso-8859-1';
$login = isset( $param['username'] ) && isset( $param['password'] );
$nl = "\r\n";
$socketLength = 4096;
$localhost = "127.0.0.1"; //this seems to work always??

//connect to the host and port
$smtpConnect = fsockopen( $param['smtp'], $port, $errno, $errstr, $timeout );
$smtpResponse = fgets( $smtpConnect, $socketLength );
if( empty( $smtpConnect ) ) {
$logArray['connection'] = "Failed to connect: $smtpResponse";
return $logArray;
}
else $logArray['connection'] = "Connected to: $smtpResponse";

//say HELO to our little friend
fputs( $smtpConnect, "HELO $localhost$nl" );
$smtpResponse = fgets( $smtpConnect, $socketLength );
$logArray['heloResponse'] = $smtpResponse;

//start a tls session if needed
if($param['secure']) {
fputs( $smtpConnect, "STARTTLS$nl");
$smtpResponse = fgets( $smtpConnect, $socketLength );
$logArray['tlsResponse'] = $smtpResponse;

//you have to say HELO again after TLS is started
fputs( $smtpConnect, "HELO $localhost$nl" );
$smtpResponse = fgets( $smtpConnect, $socketLength );
$logArray['heloResponseAfterTls'] = $smtpResponse;
}

if( $login ) {
//request for auth login
fputs( $smtpConnect, "AUTH LOGIN$nl" );
$smtpResponse = fgets( $smtpConnect, $socketLength );
$logArray['authRequest'] = $smtpResponse;

//send the username
fputs( $smtpConnect, base64_encode( $param['username'] ) . $nl );
$smtpResponse = fgets( $smtpConnect, $socketLength );
$logArray['authUsername'] = $smtpResponse;

//send the password
fputs( $smtpConnect, base64_encode( $param['password'] ) . $nl );
$smtpResponse = fgets( $smtpConnect, $socketLength );
$logArray['authPassword'] = $smtpResponse;
}

//email from
fputs( $smtpConnect, "MAIL FROM: " . $param['from'] . $nl );
$smtpResponse = fgets( $smtpConnect, $socketLength );
$logArray['mailFromResponse'] = $smtpResponse;

//email to
fputs( $smtpConnect, "RCPT TO: " . $param['to'] . $nl );
$smtpResponse = fgets( $smtpConnect, $socketLength );
$logArray['mailtoResponse'] = $smtpResponse;

//the email
fputs( $smtpConnect, "DATA$nl" );
$smtpResponse = fgets( $smtpConnect, $socketLength );
$logArray['dataResponse'] = $smtpResponse;

//construct headers
$headers = "MIME-Version: 1.0$nl";
$headers .= "Content-type: text/html; charset=$charset$nl";
$headers .= sprintf( "To: %s <%s>$nl", isset( $param['nameto'] ) ? $param['nameto'] : '', $param['to'] );
//"To: $nameto <$to>" . $newLine;

$headers .= sprintf( "From: %s <%s>$nl", isset( $param['namefrom'] ) ? $param['namefrom'] : '', $param['from'] );
//"From: $namefrom <$from>" . $newLine;

//observe the . after the newline, it signals the end of message
$str = "To: %s$nl" . "From: %s$nl" . "Subject: %s$nl$headers$nl$nl%s$nl$nl.$nl$nl";
fputs( $smtpConnect, sprintf( $str, $param['to'], $param['from'], $param['subject'], $param['content'] ) );
//"To: $to\r\nFrom: $from\r\nSubject: $subject\r\n$headers\r\n\r\n$message\r\n.\r\n");
$smtpResponse = fgets( $smtpConnect, $socketLength );
$logArray['contentResponse'] = $smtpResponse;

// say goodbye
fputs( $smtpConnect, "QUIT$nl" );
$smtpResponse = fgets( $smtpConnect, $socketLength );
$logArray['quitResponse'] = $smtpResponse;
$logArray['quitCode'] = substr( $smtpResponse, 0, 3 );
fclose( $smtpConnect );
if( $logArray['quitCode'] == 221 ) $logArray['success'] = true;
return $logArray;
}


不過E-mail這東西似乎還有很多編碼的問題需要解決,我無法很順利的用UTF-8去寄東西,又要小心Big5的衝碼字。
另外,寄件/收信人暱稱好像只能用英文??中文就算用括號也不行呢..

沒有留言: