我有一張客戶今天記錄的票據,報告稱當試圖發送附件時,PHP的mail()
函數在我的Windows 2003 Server的一個盒子上超時。PHP的mail()函數附件在Windows上是否支持一些故障?
經過調查,我能夠重現他的問題。包含30-60Kb大小的小附件的消息需要15-20秒才能被mail()
函數處理。大約360-500Kb的較大附件花費的時間比允許的最大腳本執行時間(90秒)長。
我能夠在兩臺不同的Windows 2003服務器和Windows 2008R2服務器上重現問題。我還嘗試了三種不同版本的PHP(5.2.14,5.2.17和5.3.6-根據微軟在Windows上運行PHP的建議,所有32位和所有非線程安全構建)。
在所有情況下,郵件都通過SMTP發送(即不使用sendmail實現)。我嘗試三種不同的SMTP場景:
- 交貨直接向我們的SMTP智能主機集羣(運行進出口)通過本地IIS SMTP服務
- 交付其轉發給我們的智能主機通過本地IIS SMTP服務,但與MX
- 交貨查詢和直接交付
無論如何,發送附件仍然是次優的,這意味着問題不能被固定在慢速繼電器上。
然後,我們在我們的CentOS服務器上運行相同的代碼,但沒有發現任何這些問題,幾乎立即返回mail()
函數。但是,這些服務器上的PHP配置爲使用sendmail
。
我再決定spelunk PHP源代碼,找出哪些mail()
函數的實現看起來像在ext/standard/mail.c
發現這個代碼:
if (!sendmail_path) {
#if (defined PHP_WIN32 || defined NETWARE)
/* handle old style win smtp sending */
if (TSendMail(INI_STR("SMTP"), &tsm_err, &tsm_errmsg, headers, subject, to, message, NULL, NULL, NULL TSRMLS_CC) == FAILURE) {
if (tsm_errmsg) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", tsm_errmsg);
efree(tsm_errmsg);
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", GetSMErrorText(tsm_err));
}
return 0;
}
return 1;
#else
return 0;
#endif
TSendMail()
在另一個源文件(win32/sendmail.c
)來實現。最終發送到SMTP服務器的所有數據似乎是通過一個在sendmail.c
叫Post()
功能看起來像同步傳遞:
static int Post(LPCSTR msg)
{
int len = strlen(msg);
int slen;
int index = 0;
while (len > 0) {
if ((slen = send(sc, msg + index, len, 0)) < 1)
return (FAILED_TO_SEND);
len -= slen;
index += slen;
}
return (SUCCESS);
}
的send()
功能是winsock2
功能。
我想知道如果緩衝區大小(根據下面的知識庫文章8K是默認值)還是缺少調整對大數據量有一些影響。沒有調用setsockopt()
來指定緩衝區大小或任何其他選項來優化對send()
的調用。
也許使用SMTP傳遞的Windows上的mail()
函數不打算用於發送大型郵件?
我很想知道是否有人看過這段代碼或經歷過同樣的事情。
Design issues - Sending small data segments over TCP with Winsock
只要是明確的,我們現在已經有對客戶(SwiftMailer)的替代解決方案,現在,所以這是不是讓替代品的建議。
這不是經常看到從)管理員問題,和b)用了很多代表的人。必須是NP-Hard ...:P –
我不知道在這種情況下是否有獎金。 –
郵件()的動力非常不足,從來不會將其用於任何超級基本功能。我想手動提示在此 – 2011-09-23 01:52:34