2011-09-23 77 views
6

我有一張客戶今天記錄的票據,報告稱當試圖發送附件時,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.cPost()功能看起來像同步傳遞:

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)的替代解決方案,現在,所以這是不是讓替代品的建議。

+1

這不是經常看到從)管理員問題,和b)用了很多代表的人。必須是NP-Hard ...:P –

+0

我不知道在這種情況下是否有獎金。 –

+0

郵件()的動力非常不足,從來不會將其用於任何超級基本功能。我想手動提示在此 – 2011-09-23 01:52:34

回答