[PATCH 2 of 5] e-mail: send comment and pullrequest mails with the author's name in From
Mads Kiilerich
mads at kiilerich.com
Mon Jul 13 18:36:37 EDT 2015
On 07/13/2015 09:46 PM, Thomas De Schampheleire wrote:
> On Mon, Jul 13, 2015 at 9:02 PM, Mads Kiilerich <mads at kiilerich.com> wrote:
>> On 07/13/2015 10:45 AM, Thomas De Schampheleire wrote:
>>> # HG changeset patch
>>> # User Thomas De Schampheleire <thomas.de.schampheleire at gmail.com>
>>> # Date 1436471455 -7200
>>> # Thu Jul 09 21:50:55 2015 +0200
>>> # Node ID 95c18c5fdb59f2d985e2cd8ac6db093cb3e5f884
>>> # Parent c22a219636b830bac4b6125b306f6c8506f81d99
>>> e-mail: send comment and pullrequest mails with the author's name in From
>>>
>>> When e-mails are sent for comments and pullrequest invitations, set the
>>> From
>>> header to:
>>> Author's Name <generic e-mail address>
>>
>> The rationale for this has been discussed before. It could be nice to have a
>> brief summary here in the commit message.
> Ok.
>
>> Also, I wonder if the author name should be augmented with 'something' to
>> make it clear that it not is something that should be added to address books
>> or used to reach the person with that name. Perhaps add "virtually" or some
>> other suffix?
> Is that common practice? At least, I haven't seen the 'virtually'
> suffix. I think I have seen things like:
>
> Full Name (Kallithea) <noreply at ...>
>
> So giving the application's name as suffix. What about that?
My example is probably not common practice. Your example might be
better. Or how about just hardcode adding '(Noreply)' ?
>
>>> The sender used for other e-mail types, e.g. password reset mails, is
>>> untouched and remains the value configured in app_email_from.
>>>
>>> The sender used for the SMTP envelope is untouched as well.
>>>
>>> Based on code by Cedric De Herdt.
>>>
>>> diff --git a/kallithea/lib/celerylib/tasks.py
>>> b/kallithea/lib/celerylib/tasks.py
>>> --- a/kallithea/lib/celerylib/tasks.py
>>> +++ b/kallithea/lib/celerylib/tasks.py
>>> @@ -247,7 +247,7 @@ def get_commits_stats(repo_name, ts_min_
>>> @task(ignore_result=True)
>>> @dbsession
>>> -def send_email(recipients, subject, body='', html_body='', headers=None):
>>> +def send_email(recipients, subject, body='', html_body='', headers=None,
>>> author=None):
>>> """
>>> Sends an email with defined parameters from the .ini files.
>>>
>>
>> It would be nice with a docstring explaining what 'author' is and what it is
>> used for. Looking at the code, I guess it must be a User object? Perhaps
>> just call it 'user' instead? Or rework the code to make it a more generic
>> 'sender_full_name' string?
> The original code by Cedric was giving only a string (full_contact),
> but I found it to restricting that the caller specified the way
> e-mails were formed. So I changed it to take a User object, so that
> the e-mail code has more flexibility. I can rename it to user of
> course, is that fine enough or do you prefer other changes?
I think either of them would be fine - I would just prefer a docstring
to explain which of them it is.
>
>>> @@ -259,6 +259,8 @@ def send_email(recipients, subject, body
>>> """
>>> log = get_logger(send_email)
>>> assert isinstance(recipients, list), recipients
>>> + if headers is None:
>>> + headers = {}
>>
>> If headers is passed, it is a mutable object which we will mutate. I suggest
>> creating a copy before modifying.
> Ok.
>
>>> email_config = config
>>> email_prefix = email_config.get('email_prefix', '')
>>> @@ -274,7 +276,23 @@ def send_email(recipients, subject, body
>>> log.error("No recipients specified")
>>> return False
>>> - mail_from = email_config.get('app_email_from', 'Kallithea')
>>> + # SMTP sender
>>> + envelope_from = email_config.get('app_email_from', 'Kallithea')
>>> + # From header
>>> + if author is None:
>>> + headers['From'] = envelope_from
>>
>> Why set the From header if none has been specified?
> The e-mail will always have a From header. If it is not set here, the
> SmtpMailer will default to the sender passed, currently also
> envelope_from. The next patch will change that to app_email_noreply.
>
> The code really is like this due to code evolution and so strictly
> speaking this patch could be trimmed with a few lines, but I'd argue
> that it makes little sense here as the behavior is the same and the
> next patch will need this structure anyway?
I would prefer to not have unrelated and (by themself) pointless changes
bundled together with stuff that matters. No big deal, though.
>
>>> + else:
>>> + # set From header based on author but with a generic e-mail
>>> address
>>> + # In case app_email_from is in "Some Name <e-mail>" format, we
>>> first
>>> + # extract the e-mail address.
>>
>> (It would be nice if the hints in the .ini file told which formats are
>> valid.)
> Ok.
>
>>> + import re
>>
>> Please just import globally. The re object could perhaps also be compiled
>> globally ... this is not used very often so probably no big deal.
> Ok.
>
>>> + m = re.match('.*<(.*)>', envelope_from)
>>> + if m is not None:
>>> + envelope_addr = m.group(1)
>>> + else:
>>> + envelope_addr = envelope_from
>>
>> - but I guess there is a more generic mail address parser in utils or
>> helpers that we can use?
> parseaddr could be it:
> https://docs.python.org/2/library/email.util.html
Or kallithea.lib.vcs.utils.author_email or the weird wrappers in
kallithea.lib.helpers .
>
>>> + headers['From'] = '%s <%s>' % (author.full_name_or_username,
>>> envelope_addr)
>>> +
>>> user = email_config.get('smtp_username')
>>> passwd = email_config.get('smtp_password')
>>> mail_server = email_config.get('smtp_server')
>>> @@ -285,13 +303,18 @@ def send_email(recipients, subject, body
>>> smtp_auth = email_config.get('smtp_auth')
>>> if not mail_server:
>>> - log.error("SMTP mail server not configured - cannot send mail
>>> '%s' to %s", subject, ' '.join(recipients))
>>> - log.warning("body:\n%s", body)
>>> - log.warning("html:\n%s", html_body)
>>> + log.error("SMTP mail server not configured - cannot send mail to
>>> %s", ' '.join(recipients))
>>> + log.warning("Mail details:\n"
>>> + "envelope_from: %s\n"
>>> + "headers: %s\n"
>>> + "subject: %s\n"
>>> + "body:\n%s\n"
>>> + "html:\n%s\n"
>>> + % (envelope_from, headers, subject, body, html_body))
>>
>> I agree that it can be convenient to have debug logging of the mail details
>> ... but it should only be if no mail_server has been configured.
> That is the case in the above code, or I'm misunderstanding you. All I
> did was group different warning calls in one, add some fields, and
> move the subject field to warning with the rest of the mail details.
Heh - I missed a "not".
I think it should be possible to debug envelope_from and headers even if
mail_server is configured. They are however not very relevant if the
user has the much bigger problem of not having any mail server.
/Mads
More information about the kallithea-general
mailing list