Skip to content

Fixes #71677: Pluggable Mail Transports #1778

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 78 additions & 15 deletions ext/standard/mail.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@
#endif

#ifdef NETWARE
#define EX_OK 0 /* successful termination */
#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
#define EX_OK 0 /* successful termination */
#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
#endif

#define SKIP_LONG_HEADER_SEP(str, pos) \
Expand Down Expand Up @@ -269,10 +269,6 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char
int tsm_err;
char *tsm_errmsg = NULL;
#endif
FILE *sendmail;
int ret;
char *sendmail_path = INI_STR("sendmail_path");
char *sendmail_cmd = NULL;
char *mail_log = INI_STR("mail.log");
char *hdr = headers;
#if PHP_SIGCHILD
Expand Down Expand Up @@ -335,6 +331,25 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char
MAIL_RET(0);
}

mail_module *transport = _php_find_mail_module(INI_STR("mail.transport"));
if (!transport) {
php_error_docref(NULL, E_WARNING, "Cannot find mail transport handler '%s'", INI_STR("mail.transport"));
MAIL_RET(0);
}

if (transport->send(to, subject, message, hdr, extra_cmd)) {
MAIL_RET(1);
}
MAIL_RET(0);
}
/* }}} */

int php_mail_sendmail(char *to, char *subject, char *message, char *hdr, char *extra_cmd) {
FILE *sendmail;
int ret;
char *sendmail_path = INI_STR("sendmail_path");
char *sendmail_cmd = NULL;

if (!sendmail_path) {
#if (defined PHP_WIN32 || defined NETWARE)
/* handle old style win smtp sending */
Expand All @@ -345,11 +360,11 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char
} else {
php_error_docref(NULL, E_WARNING, "%s", GetSMErrorText(tsm_err));
}
MAIL_RET(0);
return 0;
}
MAIL_RET(1);
return 1;
#else
MAIL_RET(0);
return 0;
#endif
}
if (extra_cmd != NULL) {
Expand Down Expand Up @@ -393,7 +408,7 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char
signal(SIGCHLD, sig_handler);
}
#endif
MAIL_RET(0);
return 0;
}
#endif
fprintf(sendmail, "To: %s\n", to);
Expand Down Expand Up @@ -422,9 +437,9 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char
#endif
#endif
{
MAIL_RET(0);
return 0;
} else {
MAIL_RET(1);
return 1;
}
} else {
php_error_docref(NULL, E_WARNING, "Could not execute mail delivery program '%s'", sendmail_path);
Expand All @@ -433,18 +448,18 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char
signal(SIGCHLD, sig_handler);
}
#endif
MAIL_RET(0);
return 0;
}

MAIL_RET(1); /* never reached */
return 1; /* never reached */
}
/* }}} */

/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(mail)
{
char *sendmail_path = INI_STR("sendmail_path");
char *transport_name = INI_STR("mail.transport");

#ifdef PHP_WIN32
if (!sendmail_path) {
Expand All @@ -455,6 +470,54 @@ PHP_MINFO_FUNCTION(mail)
#else
php_info_print_table_row(2, "Path to sendmail", sendmail_path);
#endif
php_info_print_table_row(2, "Mail Transport", transport_name);
}
/* }}} */

/* *********************
* Transport Modules *
********************* */

#define MAX_MODULES 32

mail_module mail_module_sendmail = {
"sendmail",
php_mail_sendmail
};

static mail_module *mail_modules[MAX_MODULES + 1] = {
&mail_module_sendmail
};

PHPAPI int php_mail_register_module(mail_module *ptr) /* {{{ */
{
int ret = FAILURE;
int i;

for (i = 0; i < MAX_MODULES; i++) {
if (!mail_modules[i]) {
mail_modules[i] = ptr;
ret = SUCCESS;
break;
}
}
return ret;
}
/* }}} */

PHPAPI mail_module *_php_find_mail_module(char *name) /* {{{ */
{
mail_module *ret = NULL;
mail_module **mod;
int i;

for (i = 0, mod = mail_modules; i < MAX_MODULES; i++, mod++) {
if (*mod && !strcasecmp(name, (*mod)->name)) {
ret = *mod;
break;
}
}
return ret;
}
/* }}} */

Expand Down
8 changes: 8 additions & 0 deletions ext/standard/php_mail.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,18 @@
#ifndef PHP_MAIL_H
#define PHP_MAIL_H

typedef struct mail_module_struct {
const char *name;
int (*send)(char *to, char *subject, char *message, char *hdr, char *extra_cmd);
} mail_module;

PHP_FUNCTION(mail);
PHP_MINFO_FUNCTION(mail);

PHP_FUNCTION(ezmlm_hash);
PHPAPI extern int php_mail(char *to, char *subject, char *message, char *headers, char *extra_cmd);

PHPAPI int php_mail_register_module(mail_module *);
PHPAPI mail_module *_php_find_mail_module(char *name);

#endif /* PHP_MAIL_H */
1 change: 1 addition & 0 deletions main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@ PHP_INI_BEGIN()
PHP_INI_ENTRY("sendmail_from", NULL, PHP_INI_ALL, NULL)
PHP_INI_ENTRY("sendmail_path", DEFAULT_SENDMAIL_PATH, PHP_INI_SYSTEM, NULL)
PHP_INI_ENTRY("mail.force_extra_parameters",NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnChangeMailForceExtra)
PHP_INI_ENTRY("mail.transport", "sendmail", PHP_INI_SYSTEM, NULL)
PHP_INI_ENTRY("disable_functions", "", PHP_INI_SYSTEM, NULL)
PHP_INI_ENTRY("disable_classes", "", PHP_INI_SYSTEM, NULL)
PHP_INI_ENTRY("max_file_uploads", "20", PHP_INI_SYSTEM|PHP_INI_PERDIR, NULL)
Expand Down