| Project: | Drupal core |
| Version: | 8.x-dev |
| Component: | mail system |
| Category: | task |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | closed (won't fix) |
| Issue tags: | needs backport to D6, needs backport to D7, regression, Usability |
Issue Summary
In Drupal 5.x, I configure the site e-mail address to be something like "Site Webmaster" <webmaster@site.com> (at the site info page: example.com/admin/settings/site-information). The effect of this is that e-mails from the site have a nicely formatted "From" field. That is, they appear to be from "Site Webmaster", rather than webmaster@site.com. Which is a bit nicer and cleaner.
In Drupal 6.x, the additional validation prevents such an e-mail address configuration. You are now limited to just the e-mail address, without a name. Hence site e-mails appear to be from just webmaster@site.com, which is just not as nice :)
Very minor style issue, I know. But is it possible to retain nice addresses, while still validating the e-mail address?
(The field validation could be altered. Or a site name field could be added to site info. Mail could then be sent from "site name" <site e-mail>)
Comments
#1
D6 uses the new function system_site_information_settings_validate, and specifically user_validate_mail to check the site_mail field, which in turns uses common.inc's valid_email function. So, there are three different ways of solving this problem, without adding a new field (and as such having to change even more code for mailing).
1) Modifiy system_site_information_settings_validate in system.admin.inc to execute a regex and split the string based on finding , and only validate the second portion which is the actual e-mail address.
2) Modify user_validate_mail to do the same stripping as above.
3) Modify the core valid_email function (not recommended, as this could have many ramifications).
Even though this was a "feature" in D5, I don't believe that it's a bug just because it's not in D6.
I'm changing the component to point the appropriate place and will leave it as a bug report until discussion can take place on whether this is a bug or a request.
#2
Thanks for the follow-up. I'd lean towards option 2 (or maybe 1) as a good way to go.
Your point about whether this a bug is a fair one. My initial reaction to D6 was, "hey, I can't do what I could in D5", hence I chose bug. But you're right it was never an explicit feature, so this could become a feature request. Of course that would mean it wouldn't be fixed until D7, wouldn't it? :(
#3
This is not just a "nice to have" feature but a serious bug, as emails w/o sender name are often penalized by raising the SPAM index value, AFAIK.
To make this implicit D5-feature explicit, I'd prefer adding a separate name field to the form. We'll have to add or change one or two strings anyway. The fact that adding a string is the lesser crime during string freeze, would be an additional argument for a separate field.
Some response would be great before any work is done on this.
#4
IMO the best we can do is to add another field for sender's name. email is not sender, so no reason to have it on the same field.
#5
Shold we follow RFC 2822 and match mailbox definition?:
http://www.faqs.org/rfcs/rfc2822.html
Note that a mailbox is composed of
mailbox = name-addr / addr-spec#6
+1 for using mailbox spec (with optional displayname angle-addr) rather than forcing addr-spec. However, such a change would have to be accompanied by a careful check that no other part of core relies on the addr-spec assumption.
If some code took it on itself to construct
"Name" <$email>anywhere, allowing$emailto already be a mailbox specification would break it.#7
Agree with Arancaytar,
The document defines an address as:
address = mailbox / group
mailbox = name-addr / addr-spec
name-addr = [display-name] angle-addr
angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
display-name = phrase
So the sender field can be : phrase "<" addr-spec ">".
I vote for modifing the core function.
#8
+1 for following the spec.
#9
This patch modifies the core function valid_email_address to adapt it to the spec. The optional new format is:
"display name" <user@domain>, the old format, without the first part, is still valid.Extensive testing is needed.
#10
Same as #9 but using & l t ; and & g t ; instead of angle chars.
#11
Why do you need to use entities in this validation - has the input already been through check_plain?
#12
@Arancaytar: Entities are not needed, but I think that for #9 to work we need to modify drupal_send_mail function
#13
Oh, so you actually have to *enter*
"Name" <mail@mail>. Well... inconvenient, but I suppose that's better than nothing. Perhaps this could be improved in a later patch.#14
Angle addresses break badly.
Address entered:
"Arancaytar Ilyaran" <arancaytar.ilyaran>Mail headers:
To: arancaytar.ilyaran@gmail.comSubject: Replacement login information for Arancaytar at Drupal
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed; delsp=yes
Content-Transfer-Encoding: 8Bit
X-Mailer: Drupal
Errors-To: "Arancaytar Ilyaran"@millhouse.dreamhost.com,
<@millhouse.dreamhost.com;, arancaytar.ilyaran@gmail.com>
Sender: "Arancaytar Ilyaran"@millhouse.dreamhost.com,
<@millhouse.dreamhost.com;, arancaytar.ilyaran@gmail.com>
Reply-To: "Arancaytar Ilyaran"@millhouse.dreamhost.com,
<@millhouse.dreamhost.com;, arancaytar.ilyaran@gmail.com>
From: "Arancaytar Ilyaran"@millhouse.dreamhost.com,
<@millhouse.dreamhost.com;, arancaytar.ilyaran@gmail.com>
Message-Id: <20080122212432.4950ACAE1@millhouse.dreamhost.com>
Date: Tue, 22 Jan 2008 13:24:32 -0800 (PST)
I'll try to get debug output too, in a bit.
#15
This is the exact content that gets passed to the PHP mail() function as its fourth (mime-headers) parameter:
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed; delsp=yes
Content-Transfer-Encoding: 8Bit
X-Mailer: Drupal
Errors-To: "Arancaytar Ilyaran" <arancaytar.ilyaran@gmail.com>
Return-Path: "Arancaytar Ilyaran" <arancaytar.ilyaran@gmail.com>
Sender: "Arancaytar Ilyaran" <arancaytar.ilyaran@gmail.com>
Reply-To: "Arancaytar Ilyaran" <arancaytar.ilyaran@gmail.com>
From: "Arancaytar Ilyaran" <arancaytar.ilyaran@gmail.com>
Somewhere along the line, it ends up as above. My guess is that the entities aren't working out...
#16
I have applied patch #9 instead of #10. Works.
Site mail entered:
"Arancaytar Ilyaran" <arancaytar.ilyaran@gmail.com>Mail headers:
To: arancaytar.ilyaran@gmail.comSubject: Replacement login information for Arancaytar at Drupal
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed; delsp=yes
Content-Transfer-Encoding: 8Bit
X-Mailer: Drupal
Errors-To: "Arancaytar Ilyaran" <arancaytar.ilyaran@gmail.com>
Sender: "Arancaytar Ilyaran" <arancaytar.ilyaran@gmail.com>
Reply-To: "Arancaytar Ilyaran" <arancaytar.ilyaran@gmail.com>
From: "Arancaytar Ilyaran" <arancaytar.ilyaran@gmail.com>
Message-Id: <20080122215206.6273ACAE1@millhouse.dreamhost.com>
Date: Tue, 22 Jan 2008 13:52:06 -0800 (PST)
#9 (non-escaped angle characters) works fine for my test, without any other modification. #10 does not.
Unless there is some other issue, I guess #9 is the one we need to use.
I am shying away from RTBCing though, because this has to be tested on another PHP setup, and with other components than the site address. For further testing, these are the references to valid_email_address() and drupal_mail() and drupal_mail_send() in core.
$ grep "valid_email_address" -R *includes/common.inc:function valid_email_address($mail) {
modules/comment/comment.module: if (!valid_email_address($edit['mail'])) {
modules/contact/contact.admin.inc: if (!valid_email_address(trim($recipient))) {
modules/contact/contact.pages.inc: if (!valid_email_address($form_state['values']['mail'])) {
modules/contact/contact.pages.inc: if (!valid_email_address($user->mail)) {
modules/system/system.module: if (!valid_email_address($form_values['recipient']) && $form_values['recipient'] != '%author') {
modules/update/update.settings.inc: if (valid_email_address($email)) {
modules/user/user.module: if (!valid_email_address($mail)) {
$ grep "drupal_mail(" -R *includes/mail.inc: * // example_mail() will be called based on the first drupal_mail() parameter.
includes/mail.inc: * drupal_mail('example', 'notify', $account->mail, user_preferred_language($account), $params);
includes/mail.inc:function drupal_mail($module, $key, $to, $language, $params = array(), $from = NULL, $send = TRUE) {
includes/mail.inc: * PHP function reference for mail()</a>. See drupal_mail() for information on
includes/mail.inc: * We deliberately use LF rather than CRLF, see drupal_mail().
includes/mail.inc: * (RFC 3676) and can be passed directly to drupal_mail() for sending.
includes/mail.inc: * We deliberately use LF rather than CRLF, see drupal_mail().
modules/contact/contact.pages.inc: drupal_mail('contact', 'page_mail', $contact['recipients'], language_default(), $values, $from);
modules/contact/contact.pages.inc: drupal_mail('contact', 'page_copy', $from, $language, $values, $from);
modules/contact/contact.pages.inc: drupal_mail('contact', 'page_autoreply', $from, $language, $values, $contact['recipients']);
modules/contact/contact.pages.inc: drupal_mail('contact', 'user_mail', $to, user_preferred_language($account), $values, $from);
modules/contact/contact.pages.inc: drupal_mail('contact', 'user_copy', $from, $language, $values, $from);
modules/system/system.module: if (drupal_mail('system', 'action_send_email', $recipient, $language, $params)) {
modules/update/update.fetch.inc: drupal_mail('update', 'status_notify', $target, $target_language, $params);
modules/update/update.module: * @see drupal_mail()
modules/user/user.module: * @see drupal_mail()
modules/user/user.module: $mail = drupal_mail('user', $op, $account->mail, $language, $params);
modules/user/user.module: drupal_mail('user', 'register_pending_approval_admin', variable_get('site_mail', ini_get('sendmail_from')), language_default(), $params);
$ grep "drupal_mail_send(" -R *includes/mail.inc: * Finally drupal_mail_send() sends the e-mail, which can be reused
includes/mail.inc: * Send the message directly, without calling drupal_mail_send() manually.
includes/mail.inc: $message['result'] = drupal_mail_send($message);
includes/mail.inc:function drupal_mail_send($message) {
modules/user/user.module: * The return value from drupal_mail_send(), if ends up being called.
#17
@Arancaytar: Thanks!
I've tried to break it on all forms that a valid email is involved but I couldn't and the regex added is optional.
The angle address works ok for me, so I'm attaching #9 again with a comment about the two valid formats.
#18
On reading that regex again...
Won't the following two be "valid" email addresses?
"Arancaytar Ilyaran" <arancaytar.ilyaran@gmail.comarancaytar.ilyaran@gmail.com>
I may have a bit of a gap in my understanding of substring expressions, however. Some of those question marks look odd...
#19
No, this addresses are not valid, the trick here is the code:
$angle = '(?(1)>)';Is a conditional regex that *only* is validated when the (1) regex has been tested and is TRUE.
The (1) regex is the display name part including the white space and the first angle:
$name = '((?:"[^\"\f\n\r\t\v]+" <))?';Here, we specifically look for quotes surrounding a phrase (one or more words, no control characters), but this is all optional so it can be FALSE, when not valid or nothing. Then $angle only is active whe this is TRUE.
#20
Thanks for teaching me something new about regex! I think I remember dozens of places in my own code where I can clean up a regular expression or cut down from two to a single one using this particular trick.
In any case, I haven't found any errors on applying this patch. Perhaps another reviewer should test it, but as far as I'm concerned, it's ready.
#21
Looks like this is a feature addition (in email validation) and also an API break since those expecting that their validation is done on an email *address* will get names sneaking in where they don't want it (like on the user account email field).
#22
However, the "feature" it adds was in D5 and removed by regression. As the site email was allowed to contain a name in D5, any expectation of site email being a pure address would have been broken in D5, and will be broken in D6 for upgraded sites that retain their newly invalidated site email field. So at least this field can contain a name without adding any additional API problems. I'll readily admit that the other references to valid_email_address assume absence of names.
Can we at least make the mailbox spec optional and default it to false?
<?php
function valid_email_address($mail, $allow_name = FALSE) {
...
}
function system_site_information_settings_validate() {
...
$validate_email = valid_email_address($site_mail, TRUE);
}
?>
#23
Ok, so this should be divided:
a) A feature request to include the validation on the core function: http://drupal.org/node/214114.
b) A patch to modify 'system_site_information_settings' function because this is the part affected by the issue.
This patch looks if there is a display name inside the mail parameter and extracts the address part to pass it to validation.
#24
Hm, $allow_name sounds like reasonable for now.
#25
$allow_name implemented.
As site-info uses user_validate_email for generating the appropriate form errors, user_validate_email takes the $allow_name = FALSE argument and passes it on to valid_email_address.
NOTE - this patch is racing against another one that fixes the "trailing period in hostname" bug. Both patches change the same lines of common.inc, and the losing patch will require a (mostly trivial) conflict-resolving re-roll.
#26
Status update.
#27
I've tested this patch and it appears to work. I can now enter e-mail addresses with a sender name, a-la Drupal 5.x.
I also tried several almost-correct addresses with sender names and they were all flagged as errors. So I think what's there is good to go.
I think the use of extra variables in the functions and the defaults chosen should prevent any breaks to existing code.
My only concern is whether there are more places where support for a sender name could be enabled. I don't feel I can comment on the entire code base. Perhaps someone else ...
#28
I did a file search for "valid_email_address", and I believe there are a couple places where it is used:
I tested it in all these locations and they seem to be working nicely. You could use the sender's name in Drupal 5, so renaming this issue to a regression issue.
This attached patch adds code documentation for the new argument passed to the
valid_email_addressfunction.#29
Possible follow-up issue: The installer "recommends" using the same address for site contact and the root user. Javascript code copies the form value from one email field to the other automatically.
With this patch, the site contact address will allow values that a user address does not. It is usually a reasonable expectation that the suggested defaults actually pass validation.
However, that shouldn't be a show-stopper, because it's pretty clear to the user what is happening, and if they know what they're doing when they add a name to the first field, they should also know that the second field may not have a name.
#30
While I understand that this is a regression, I don't think that API change is a good idea now. Please revisit the issue in Drupal 7. For Drupal 6, the form and the mail is equally alterable, so there are multiple places to solve this. This regression appeared at all, because there was no email validation in Drupal 5 there.
#31
Hm. Okay. Of course, if we had known this two weeks ago, we could have spent more time on critical issues instead of implementing the $allow_name argument to get this into 6.x... ;)
#32
So, for DRUPAL-6, we remove the validation on the site information settings page, and for HEAD, we add $allow_name to
valid_email_address. Does that sound reasonable?#33
In D6, I'd rather use the site name as name and site email as email in the outgoing mail, if you insist on having a name by default. Checking the format of an email input field is IMHO an improvement not a bad thing to have.
#34
Like this?
<?phpfunction drupal_mail($module, $key, $to, $language, $params = array(), $from = NULL, $send = TRUE) {
$default_from = variable_get('site_mail', ini_get('sendmail_from'));
// The ini variable may not conform to the addr-spec format site_mail has. A check is needed.
if (is_valid_email($default_from)) {
$default_from = '"'. variable_get('site_name', 'Drupal') .'" <'. $default_from .'>';
}
?>
This patch is for 6.x.
#35
Note: I don't know what characters the site name allows, and if it potentially needs to be check_plained or otherwise filtered before conforming to RFC 2822.
#36
Subscribing.
#37
Anyone know what happened here? Thanks!
#38
#34 patch works great, thanks. This should definitely be included in core IMHO.
#39
Subscribing.
#40
So a i reading this right? you need to patch core in order to get the site email address to show up prefaced with an actual name like
"My Site"
#41
This issue is one major release old and needs to be moved up.
Incidentally, on giving this some more thought I am wondering if it might not make more sense to drop support for this completely. Instead of allowing the email address to contain a specific name, just format outgoing From headers as
"$site_name" <$site_mail>#42
I disagree it should be dropped. That method might work but it's hardly user friendly!
#43
I'm not 100% either.
#44
patch (#9) is working fine... i mean email field is accespting both name & mail address.... but while sending a mail from that mail address its giving problem like this
warning: mail() [function.mail]: SMTP server response: 501 5.5.4 Invalid Address in C:\wamp\www\drupal-6.11\includes\mail.inc on line 193.
Unable to send e-mail. Please contact the site administrator if the problem persists.
#45
patch (#9) is working fine... i mean email field is accespting both name & mail address.... but while sending a mail from that mail address its giving problem like this
warning: mail() [function.mail]: SMTP server response: 501 5.5.4 Invalid Address in C:\wamp\www\drupal-6.11\includes\mail.inc on line 193.
Unable to send e-mail. Please contact the site administrator if the problem persists.
#46
I agree with Arancaytar on using the site name as the human readable part of the
From:header.#47
@GregoryHeller You could also create a custom module and do a hook_mail_alter
function custom_module_mail_alter(&$message){
$default_from = variable_get('site_mail', ini_get('sendmail_from'));
if($message['from'] == $default_from){
$message['from'] = '"'. variable_get('site_name', 'Drupal') .'" <'. $default_from .'>';
$message['headers']['From'] = $message['headers']['Sender'] = $message['headers']['Return-Path'] = $message['headers']['Errors-To'] = $message['headers']['Reply-To'] = $message['from'];
}
}
#48
Hi guys
Personally I think this is quite important for professional sites. People just tend to overlook mails that are not formatted nicely.
I tried jcruz's module-hack and it works like the bizz! Would be easy to extend this further into core...
Bryan
#49
This needs to stay at 7.x and back ported from there.
#50
Another workaround, which I just tested, is to edit the variables table entry directly. I used the "Variable editor" link in the Devel module block, but presumably you could use PHPMyAdmin or another database client tool.
#51
The custom module in #47 is a good approach and works well for me. I do feel that this feature should be in core though.
#52
Mail 'from the system' ($from argument is omitted in drupal_mail) should use "Site name" <site mail> as its From: header. Any disagreements? Please review.
#53
I meant "Site name" <site mail> in #52 :)#54
Tagging with usability, since I think seeing the name of the website in your inbox is less confusing than just seeing whatever the site_mail is set to.
#55
#56
Boing.
#57
Re-test of valid_email_1.patch from comment #10 was requested by lot007.
#58
So how it looks now ? Is there any module for D6 which can give a simple site name to the email sender name ?
I use 6.15 and still have only option for email address. No name.
Subscribing
#59
+1
#60
Hello,
I tried the patches in
Hello,
I tried both patches #34 and #52 but I could not get the site emails to come "from" the site name.
Do I need to do anything else besides applying those patches?
Jason
#61
#52: nice_from_header.patch queued for re-testing.
#62
same as #60, wonder if the method that includes module and not hacking core would work better
#63
If site_name contains 8bit characters, the From header line becomes
From: =?UTF-8?B?InTDqXN0IiA8Zm9vQGV4YW1wbGUuY29tPg==?=. My mail server changes this toFrom: =?UTF-8?B?InTDqXN0IiA8Zm9vQGV4YW1wbGUuY29tPg==?=@mail.example.org, and my mail client displays it as “tést @mail.example.org”.#64
Too late for this to get into D7 now, moving to D8...
#65
Subcribing
#66
We'd better move it to Drupal 9, so this patch makes it out in time for Duke Nukem Forever.
Come on, guys, this can't be THAT hard to include in core already.
#67
For now, it looks like the Personalized E-mails module will address this for D6.
#68
Not convinced that this can’t easily be addressed in D7 (and D6), I added this issue and a corresponding patch:
#69
My solution to this problem is I was already using the Mime Module and by changing the site email in it's settings page to something like "Site Name" it bypasses the normal validation and also updates the email in the site settings page. I don't even have to have "send html emails" turned on in mime mail's settings, as long as the module is installed.
#70
Subscribing.
#71
Mime Module did not work for me. Any other solutions?
#72
an anyone else confirm that http://drupal.org/project/pmail will take care of this without an issue?
#73
Subscribe
#74
Verified PMail will take care of this
#75
I just tested PMail. It works. Didn't even have to configure the module!
#76
I confirm that in Drupal 6.20 installing
http://ftp.drupal.org/files/projects/pmail-6.x-1.x-dev.tar.gz
results in the site name followed by the email address you specify in
/admin/settings/site-information
and the email address appears in angle brackets. I also think a better solution is desired for the future.
My concern as Pancho mentioned in #3 is that the email address alone appears spammy. Without Pmail, when importing users, our automated email invitations ended up in junk email and spam folders, so this was problematic for us until Pmail resolved it.
I also agree with carlos8f that this is to some extent a usability issue since a site name is more likely to be recognized than the email address specified in
/admin/settings/site-information
The dev release of the Personalized E-mail module seems to solve the problem nicely for D6, but it is not clear to me if this might also work as a workaround for D7.
#77
I'm confused how such a seemingly simple D6 issue can remain open for over 3 years, and in the meantime get reassigned to 2 versions after the original?! Providing the site name in the From header is basic core functionality. It shouldn't require the addition of a contrib module to fix.
#78
I attached version of patch #34 that works wit non-ASCII characters in site_name. This patch is for Drupal 6.x.
#79
Re-rolled against 8.x using current patch standards.
#80
Bah. regression should be "bug report" not "feature request".
#81
The last submitted patch, drupal_mail-209672-79.patch, failed testing.
#82
Oops.
#83
d8 patch still applies.
Rolled d7 and d6 versions.
Note that this fixes a regression of functionality available in d5 (!!!), hence the backports.
#84
Slight improvement over #82:
$default_fromis both non-empty and valid, because an empty string is also a valid email address.From:header twice.#85
The last submitted patch, drupal_mail-209672-84.patch, failed testing.
#86
silly me. Corrected.
#87
#88
#86: drupal_mail-209672-86.patch queued for re-testing.
#89
#90
#91
#86: drupal_mail-209672-86.patch queued for re-testing.
#92
#86: drupal_mail-209672-86.patch queued for re-testing.
#93
#86 still applies cleanly to 8.x. I think it just needs to be reviewed or is there another reason this issue has stagnated?
#94
Yup; it needs review. I'd do it myself, but the person who authored or last modified a patch should not review their own work.
If you feel up to it, read the (updated) Patch review guidelines and feel free to submit your own review. It's a great learning experience.
#95
#86: drupal_mail-209672-86.patch queued for re-testing.
#96
This is for 7.8. It works like a charm.
root@voyage:~# diff -u -p modules/contact/contact.admin.inc{.bak,}
--- modules/contact/contact.admin.inc.bak 2011-10-14 12:00:25.000000000 +0200
+++ modules/contact/contact.admin.inc 2011-10-14 12:31:15.000000000 +0200
@@ -136,7 +136,8 @@ function contact_category_edit_form_vali
foreach ($recipients as &$recipient) {
$recipient = trim($recipient);
- if (!valid_email_address($recipient)) {
+ preg_match('/^"[^\"\f\n\r\t\v]+" <(.+)>$/', $recipient, $matches);
+ if (user_validate_mail($matches ? $matches[1] : $recipient)) {
form_set_error('recipients', t('%recipient is an invalid e-mail address.', array('%recipient' => $recipient)));
}
}
root@voyage:~#
#97
Please read and understand the backport policy before changing the version, or assigning yourself to an issue. Thank you.
This issue has been stalled for five months while awaiting a review of the patch in #86.
If nobody is willing to provide such a review (and RTBC), this issue should be closed (won't fix).
#98
Closing for lack of interest. Please re-open only if you are willing to provide a patch review.
#99
Just go for mimemail projet http://drupal.org/project/mimemail
#100
#34 is how people expect this should work