2011-09-23 40 views
6

Tôi đã có vé được khách hàng ghi lại hôm nay báo cáo rằng chức năng mail() của PHP đã hết thời gian trên một trong các hộp Máy chủ Windows 2003 của chúng tôi khi cố gửi tệp đính kèm.Tệp đính kèm chức năng mail() của PHP có hỗ trợ một chút bị hỏng trên Windows không?

Khi điều tra tôi đã có thể tái tạo sự cố của anh ấy. Thư có chứa tệp đính kèm nhỏ ở kích thước khoảng 30-60Kb mất 15-20 giây để được xử lý bởi hàm mail(). Các tệp đính kèm lớn hơn khoảng 360-500Kb mất nhiều thời gian hơn thời gian thực thi kịch bản tối đa được phép (90 giây).

Tôi đã có thể tạo lại sự cố trên hai máy chủ Windows 2003 khác nhau và máy chủ Windows 2008R2. Tôi cũng đã thử ba phiên bản PHP khác nhau (5.2.14, 5.2.17 và 5.3.6 - tất cả 32 bit và tất cả các xây dựng không an toàn theo đề xuất của Microsoft để chạy PHP trên Windows).

Trong mọi trường hợp, thư được gửi qua SMTP (nghĩa là không sử dụng triển khai gửi thư). Tôi cố gắng ba kịch bản SMTP khác nhau:

  • giao hàng trực tiếp đến cụm máy chủ thông minh SMTP của chúng tôi (chạy exim)
  • giao hàng qua địa phương IIS SMTP Service đó chuyển tiếp đến Máy chủ thông minh của chúng tôi
  • giao hàng qua địa phương IIS SMTP Service nhưng với MX tra cứu và giao hàng trực tiếp

Bất kể điều gì ở trên, việc gửi tệp đính kèm vẫn chưa được tối ưu hóa có nghĩa là sự cố không thể được ghim trên chuyển tiếp chậm.

Sau đó, tôi chạy cùng một mã trên các máy chủ CentOS không hiển thị bất kỳ vấn đề nào trong số này, chức năng mail() được trả về gần như ngay lập tức. Tuy nhiên PHP trên các máy chủ này được cấu hình để sử dụng sendmail.

sau đó tôi quyết định spelunk mã nguồn PHP để tìm hiểu những gì thi hành mail() chức năng trông giống như và phát hiện mã này trong 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() được thực hiện trong một tập tin nguồn (win32/sendmail.c). Cuối cùng tất cả các dữ liệu được gửi đến một máy chủ SMTP dường như được thông qua đồng bộ thông qua một chức năng gọi là Post() trong sendmail.c trông giống như:

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); 
} 

Chức năng send() là một chức năng winsock2.

Tôi tự hỏi nếu kích thước bộ đệm (8K là mặc định theo bài viết KB dưới đây) hoặc thiếu điều chỉnh là có một số tác động ở đây cho số lượng lớn dữ liệu hơn. Không có cuộc gọi nào đến số setsockopt() để chỉ định kích thước bộ đệm hoặc bất kỳ tùy chọn nào khác để tối ưu hóa các cuộc gọi đến send().

Có lẽ chức năng mail() trên Windows sử dụng phân phối SMTP không có ý định được sử dụng để gửi email lớn?

Tôi muốn biết liệu có ai khác đã xem mã này hoặc trải nghiệm cùng một điều hay không.

Design issues - Sending small data segments over TCP with Winsock

Chỉ cần được rõ ràng, chúng tôi đã có một giải pháp thay thế cho khách hàng (SwiftMailer) ở vị trí bây giờ vì vậy đây không phải là về việc kiến ​​nghị giải pháp thay thế.

+1

Nó không thường xuyên bạn sẽ thấy một câu hỏi từ a) một admin, và b) một người nào đó với rất nhiều đại diện. Phải là NP-Hard ...: P –

+0

Tôi tự hỏi liệu một khoản tiền thưởng có theo thứ tự trong trường hợp này hay không. –

+0

mail() là rất yếu, không bao giờ sử dụng nó cho bất cứ điều gì đó không phải là siêu cơ bản. Tôi nghĩ rằng các hướng dẫn sử dụng tại đây –

Trả lời

1

Suy nghĩ của tôi sẽ sử dụng http://glob.com.au/sendmail/ trên Windows với lớp Thư PEAR: http://pear.php.net/package/Mail. Điều này có thể là một giải pháp cho thời gian chờ mà bạn đang gặp phải. Tôi nghĩ rằng điều này sẽ không thể bỏ qua bộ đệm, nhưng tôi nghĩ rằng nó sẽ có giá trị một shot.

Ngoài ra, tôi chưa bao giờ sử dụng nó, nhưng tôi đã nghe những điều tốt đẹp về SwiftMailer: http://swiftmailer.org/

+0

Không sao, tôi đã đề xuất SwiftMailer khá đẹp. – Kev

Các vấn đề liên quan