After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 585577 - Wrong FROM in envelope during SMTP negotiation
Wrong FROM in envelope during SMTP negotiation
Status: RESOLVED WONTFIX
Product: evolution
Classification: Applications
Component: Mailer
2.26.x (obsolete)
Other Linux
: Normal normal
: ---
Assigned To: evolution-mail-maintainers
Evolution QA team
evolution[smtp]
: 595048 621585 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2009-06-12 15:10 UTC by Fabien Tassin
Modified: 2013-12-19 20:09 UTC
See Also:
GNOME target: ---
GNOME version: 2.27/2.28


Attachments
fix v0 (1.24 KB, patch)
2009-12-02 14:54 UTC, Fabien Tassin
needs-work Details | Review
fix v1 (2.14 KB, patch)
2012-06-28 17:25 UTC, Fabien Tassin
needs-work Details | Review
fix v2 (2.01 KB, patch)
2012-08-03 18:18 UTC, Fabien Tassin
reviewed Details | Review
fix v3 (5.77 KB, patch)
2013-04-05 21:12 UTC, Fabien Tassin
reviewed Details | Review
fix v4 (5.86 KB, patch)
2013-04-08 12:29 UTC, Fabien Tassin
none Details | Review

Description Fabien Tassin 2009-06-12 15:10:17 UTC
(using evolution-data-server 2.26.2 on Ubuntu Karmic)

I have several accounts configured in evolution, including one to send emails
using my corporate email address. It works fine when i send emails with that
address except when the target is in my corporate domain.

Example:

my local hostname is foo.localdomain.org
my corporate email is first.last@corporate.com

I have an account in evolution with first.last@corporate.com as Identity/Email
Address and a SMTP server with AUTH in my local domain, say smtp.localdomain.org

When i post to whatever@corporate.com, it bounces back with:

554 5.7.1 <first.last@corporate.com>: Sender address rejected:
domain use is reserved

If I try the same thing with Mutt (same From, same SMTP server, same AUTH, from
the same host), it works fine.

I analyzed the SMTP conversation in both cases, here is what I see:

mutt:

220 relay.corporate.com ESMTP service ready - 14/mso RL.PUB
EHLO foo.localdomain.org
250-relay.corporate.com
250-PIPELINING
250-SIZE 20971520
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
MAIL From:<fta@foo.localdomain.org> SIZE=918 RET=HDRS
250 2.1.0 Ok

.. and the email is correctly sent.

evolution:

220 relay.corporate.com ESMTP service ready - 10/aub RL.PUB
EHLO foo.localdomain.org
250-relay.corporate.com
250-PIPELINING
250-SIZE 20971520
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
MAIL From:<first.last@corporate.com> SIZE=790
554 5.7.1 <first.last@corporate.com>: Sender address rejected:
domain use is reserved

.. and i get a bounce.

Looking at camel-smtp-transport.c, it seems the 'MAIL From' part for the
envelope is derived from the Identity in the Account, while it should be more
related to the real hostname. The From for the regular headers should of course
be the one from the Identity. Evolution should not try too hard to spoof the
envelope, or at least provide a pref/knob to allow/prevent that.
Comment 1 Akhil Laddha 2009-07-29 13:07:24 UTC
looks dupe of bug 490237 , see bug 582991 also 
Comment 2 Fabien Tassin 2009-07-29 13:38:30 UTC
hm, i don't think so. In my case, it's not a matter of using the wrong SMTP server from all those configured. It's about talking to it properly, i.e. don't pretend we're someone we're not.
Comment 3 Matthew Barnes 2009-09-13 14:29:51 UTC
*** Bug 595048 has been marked as a duplicate of this bug. ***
Comment 4 Fabien Tassin 2009-11-17 17:49:06 UTC
No feedback from anyone? /me sad

In camel/providers/smtp/camel-smtp-transport.c, smtp_send_to() creates the FROM for the *envelope* from the 'from' parameter it received from camel_transport_send_to(), so it's coming from evolution itself, i.e. from the mail headers as shown here:

evolution-2.28.1/mail/mail-ops.c:

        /* Check for email sending */
        from = (CamelAddress *) camel_internet_address_new ();
        resent_from = camel_medium_get_header (CAMEL_MEDIUM (message), "Resent-From");
        if (resent_from) {
                camel_address_decode (from, resent_from);
        } else {
                iaddr = camel_mime_message_get_from (message);
                camel_address_copy (from, CAMEL_ADDRESS (iaddr));
        }
        ...
          camel_transport_send_to(xport, message, from, recipients, ex);


This is just called spoofing. This has nothing to do with multiple accounts. It's just that envelope spoofing won't work with servers blocking that (internal emails coming from the outside).

Mutt is wise to always use whoami@fqdn for the FROM in the envelope, while leaving the From in the headers untouched.

Now, i'm not sure if the bug is in evolution-data-server or in evolution, or both.
Comment 5 Jeffrey Stedfast 2009-11-20 14:12:20 UTC
This is a bug in Evolution itself, it needs to provide Camel with the proper email address of the sender. I guess it probably shouldn't be getting it from the message headers, but rather from the account info.

Should be simple for someone to fix.
Comment 6 Fabien Tassin 2009-12-02 14:54:08 UTC
Created attachment 148917 [details] [review]
fix v0

I gave it a try and produced a patch that i've been using successfully for ~2 weeks now.
I don't consider it clean, but here is it anyway.
Comment 7 Matthew Barnes 2009-12-03 21:05:42 UTC
Does the domain name in the "MAIL FROM" address have to be fully-qualified, or could we get away with whatever gethostname() returns?
Comment 8 Fabien Tassin 2009-12-03 21:35:55 UTC
Here is what the RFC says about it:


         The first step in the procedure is the MAIL command.  The
         <reverse-path> contains the source mailbox.

            MAIL <SP> FROM:<reverse-path> <CRLF>

         This command tells the SMTP-receiver that a new mail
         transaction is starting and to reset all its state tables and
         buffers, including any recipients or mail data.  It gives the
         reverse-path which can be used to report errors.  If accepted,
         the receiver-SMTP returns a 250 OK reply.

         The <reverse-path> can contain more than just a mailbox.  The
         <reverse-path> is a reverse source routing list of hosts and
         source mailbox.  The first host in the <reverse-path> should be
         the host sending this command.

My understanding of this is that it says the 1st reverse-path should be the source mailbox + local machine which has to be routed, so if the remote speaker is not in the same domain, errors will never reach the source unless a fully-qualified reverse-path was used.
Comment 9 Matthew Barnes 2009-12-03 23:13:57 UTC
That makes sense.  Might be nice for Camel to make the FQDN available on it's own instead of having to dig it out of a Message-ID string, but I think your approach is fine for now.

I asked a GIO maintainer if he would consider adding some kind of "give me my FQDN" function to the library and his answer was that strictly speaking we should be extracting it from a connected socket.  Since this logic runs before a connection is ever made, perhaps it should be moved into Camel such that camel_transport_send_to() automatically replaces a NULL "from" address with "whoami@fqdn" (or I guess that would be up to each transport provider to do).
Comment 10 Alexander Sack 2010-03-11 13:25:43 UTC
so we can commit the current patch here?
Comment 11 Matthew Barnes 2010-03-15 22:03:14 UTC
Because this is such a critical section of code I'm going to hold off on committing until 2.31.  If the patch fares well in 2.31 we can look at backporting it to a 2.30 update.
Comment 12 Fabien Tassin 2010-05-26 13:23:47 UTC
any update?

I'm now running 2.30.1.2 and i'm still suffering from this (i can't use evolution at/for work).

My patch no longer applies due to the refactoring that happened since i wrote it.
I'm not sure how to do it now that mail_config_get_default_account() is gone.
Comment 13 Matthew Barnes 2010-05-26 13:30:02 UTC
Thanks for the reminder, I'll take a look at this again.

The function got moved and renamed to e_get_default_account() in e-util/e-account-utils.h.
Comment 14 Matthew Barnes 2010-05-29 03:20:13 UTC
Patch committed to master in:
http://git.gnome.org/browse/evolution/commit/?id=a52f00a9c9c00ecf06ac7179742ceb15e9971c5d
Comment 15 Milan Crha 2010-06-01 10:21:24 UTC
Reopening, I reverted this patch in commit b3f8d47 because I cannot send message through my IMAP account with an error:
> Error while Sending message.
> MAIL FROM command failed: <mcrha@localhost>...
> Real domain name required for sender address
Comment 16 Fabien Tassin 2010-06-01 11:54:10 UTC
hm, in my case, it's always @my_fqdn, never @localhost.
Do you mean that all your message-ids are always @localhost too?
Comment 17 Matthew Barnes 2010-06-01 12:23:04 UTC
Mine are.  Turns out I have the same problem as Milan.

e.g.  Typical sent message:

    From: Matthew Barnes <mbarnes@redhat.com>
    ...
    Message-ID: <1275276671.26525.12.camel@localhost.localdomain>
Comment 18 Matthew Barnes 2010-06-01 12:27:17 UTC
In my situation I'm typically on my home network and accessing Red Hat's SMTP server remotely, and my home network has no registered domain name.  Pretty common scenario.
Comment 19 Fabien Tassin 2010-06-01 12:31:47 UTC
d'oh! this is bad.

maybe it should default to camel_mime_message_get_from(message) when hostname
(as extracted from camel_header_msgid_generate()) is found to be
"localhost.localdomain" or "localhost".
Comment 20 Milan Crha 2010-06-02 08:16:52 UTC
Might not be that easy, I'm afraid, as you can have your domain name set only locally, or even the real domain name, but the remote server may reject your request because it expects only a domain name same as your email address, to not allow you using the SMTP server for sending addresses from different domains.
Comment 21 Fabien Tassin 2010-06-02 09:25:26 UTC
note that this is exactly the reason i filed the bug initially.
My SMTP servers at work (a very big company) reject all my emails sent from outside because evolution pretends i'm from within, while I'm not. Hence the patch tries to stop pretending that (stop spoofing) and really say (in the SMTP envelope only) where i'm really writing from.

imho, localhost(.localdomain) is a broken setup for SMTP, even if it's unfortunately common.

what i propose looks like this:

msgid = camel_header_msgid_generate(); /* => xxx@fqdn or xxx@localhost.localdomain */
if (msgid matches '@localhost.localdomain') {
  addr = camel_mime_message_get_from(message);  /* as before */
  from = ...(addr)
}
else {
  account = e_get_default_account(); /* => username */
  from = compose_email_address(account, msg_id); /* => username@fqdn */
}

remember it's the "From" for the SMTP transaction, not the "From:" for the headers, which still comes from the profile.

if it's not acceptable, like if you want the default to stay the same as the email in the profile (even if it's not true and it's spoofed), the only option to solve my problem would be to allow me to specify a non-default value in the profile(s).. but i can't propose a patch for that, i have absolutely no idea how to touch to the profiles.
Comment 22 Matthew Barnes 2010-06-15 09:45:36 UTC
*** Bug 621585 has been marked as a duplicate of this bug. ***
Comment 23 Fabien Tassin 2012-06-28 17:25:07 UTC
Created attachment 217553 [details] [review]
fix v1

Here is the patch updated to fit 3.5.3.1 (after the EAccount transition).
It addresses the localhost.localdomain/localhost issue mentioned before by not doing anything when it happens (i.e. use the From).
Comment 24 Matthew Barnes 2012-06-29 15:42:27 UTC
Comment 21 sounds like a reasonable policy.

Only change I would make to the policy is: earlier on in that function we look for an "X-Evolution-Identity" header and extract some account details based on that header value if can.  We should also try to extract an email address based on that header value, and otherwise fall back to the default mail identity.

Also, this logic is getting complicated enough that I'd like it split off into a separate mail_session_get_sender_address() function, which returns a newly-allocated string containing the email address to use for the MAIL FROM command.
Comment 25 Fabien Tassin 2012-08-03 18:18:57 UTC
Created attachment 220279 [details] [review]
fix v2

Re-posting the patch with the tiny leaks (spotted by mcrha) fixed.

@mbarnes: about moving that to a separate mail_session_get_sender_address() function, I read the surrounding code carefully and I'm not really sure how to do it best.

I see 4 locations where it could be useful:
1/ where i put it in my patch (that's where it is useful for my use case)
2/ in the (similar) "resent" branch of the enclosing if/else.
3/ & 4/ as you mentioned, where the source is derived from the X-Evolution-Identity header, either early or via the extension.

But those 4 cases seem to require different parameters, the raw header or msg-id, the source or extension. ...
I'm not really sure how to do that properly.

Please advise.
Comment 26 Fabien Tassin 2013-01-23 13:59:59 UTC
@mbarnes: would you re-land my last patch if my logic was put behind a g_settings boolean, disabled by defaut?
if so, how should this key be named?
Comment 27 André Klapper 2013-03-27 08:47:45 UTC
Matthew: Could you answer comment 26, please?
Comment 28 Milan Crha 2013-03-27 10:04:03 UTC
Review of attachment 220279 [details] [review]:

With respect of a GSettings option, let's add it into
   evo/data/org.gnome.evolution.mail.gschema.xml.in
as a boolean key 'send-with-hostname-from' with default to 'false'. Then, a helper function to get a hostname can create a new GSettings instance, read from this key, and if it's set to FALSE, then simply return NULL.

::: libemail-engine/e-mail-session-utils.c
@@ +773,3 @@
+		const gchar *extension_name;
+		gchar *who;
+		gchar *res;

define variables only there where needed

@@ +776,3 @@
+
+		/* Don't get the 'from' from the headers.
+		 * See https://bugzilla.gnome.org/show_bug.cgi?id=585577

we usually do not cite bug links/numbers in the code, the most for (temporary) workarounds.

@@ +782,3 @@
+		 * fallback to using the 'from'.
+		*/
+		hostname = strchr ((fake_msgid = camel_header_msgid_generate ()), '@');

while I'm against code duplication, the code behind this function is not that complicated, and as a side effect increases its internal counter, thus what about to extract relevant parts of that function into a helper function into this file, which will simply return either host name to be used or NULL?

@@ +790,3 @@
+			camel_address_copy (from, CAMEL_ADDRESS (addr));
+		}
+		else {

these two lines should be one line:
    } else {

@@ +805,3 @@
+			        *p = '\0';
+			}
+			res = g_strconcat (who, "@", hostname, NULL);

this one is still leaking
Comment 29 Fabien Tassin 2013-04-05 21:12:19 UTC
Created attachment 240800 [details] [review]
fix v3

Here is the patch updated, hopefully taking into account your previous review.
Comment 30 Milan Crha 2013-04-08 11:23:31 UTC
Review of attachment 240800 [details] [review]:

Thanks for the update. The patch looks good, I have only few really minor concerns about it, as indicated below.

::: libemail-engine/e-mail-session-utils.c
@@ +825,3 @@
+			return NULL;
+	}
+	return g_strdup (cached_hostname);

does it make sense to strdup here? It does not, from my point of view.

@@ +831,3 @@
+e_mail_session_set_smtp_return_path (CamelAddress *from,
+				     EMailSession *session,
+				     CamelMimeMessage *message)

what about naming the function:
e_mail_session_set_from_address (EMailSession *session,
	CamelMimeMessage *message,
	CamelAddress *from)

@@ +870,3 @@
+		        gchar *p;
+		        p = strchr (who, '@');
+		        *p = '\0';

just to be on a safe side, check if p != NULL
Comment 31 Fabien Tassin 2013-04-08 12:29:45 UTC
Created attachment 240943 [details] [review]
fix v4

I initially named the function with smtp_return_path to match the wording of the RFC snippet I posted above ("FROM <return-path>" in the SMTP transaction, vs "From:" header in the message). Anyway, I don't mind either way.

Here is the patch updated once again.
Comment 32 David Woodhouse 2013-04-08 13:19:37 UTC
This approach is not correct. You must not use the local hostname in the SMTP 'MAIL FROM', otherwise known as the reverse-path. The address of the account was the correct thing to put there.

If you break your email by putting a bogus reverse-path on it, you'll break the reliability of the whole system because you'll never receive bounces when your messages don't get through. And in fact some recipients will notice that brokenness "up front" and refuse to accept your messages at all. Not that you'll notice...

The real problem here seems to be that either the reporter's mail server, or the reporter's installation of Evolution, is misconfigured. Either he's within the company "trusted" network and mail sent with SMTP should be accepted as being from within the company. Or he's *outside* the company network, and he ought to have authenticated before attempting to send the email.

Either way, this patch isn't a fix. It isn't even a viable workaround. Please do *not* apply this.
Comment 33 Fabien Tassin 2013-04-08 14:44:49 UTC
wrong, I beg to differ. It has nothing to do with authentication.

My patch introduces a feature to set the reverse path to the true (as in not-spoofed) and routable mailbox (assuming the local machine is properly configured), exactly what the venerable Mutt and its predecessors have been doing since.. well, forever.

I understand that there are many cases when the 2nd criteria is difficult to meet (NAT..), hence the feature being disabled by default. But I assume those users also have difficulties with Mutt (their getaddrinfo is most probably failing or bogus)
Comment 34 David Woodhouse 2013-04-08 15:41:37 UTC
If the local machine is properly configured as a 'traditional' unix host would have been, with an MTA of its own, then you probably don't want to use SMTP at all. Just feed the message to /usr/sbin/sendmail instead. That's what mutt does by default. And Evolution does have a sendmail transport which would do just that, although I'm not sure how to make it get *used* for a given mail account.

However, it is the *wrong* thing to do in almost all circumstances. Yes, it's true that old terminal-based MUAs designed for traditional UNIX environments will do it by default. That doesn't make it right for Evolution.

The reverse-path used in SMTP is the address to which bounces will be sent if your outbound mail cannot be delivered. And if it's not a valid, routable mailbox, then many recipients may refuse to accept the message you're sending.

In all normal circumstances it should be the same as the From: header (or Resent-From: in some cases) on the message you are sending.

Your problem here really is a misconfiguration by your company mail servers. They are broken, because they're administered by someone who wrongly thinks that they'll never see a reverse-path of 'first.last@example.com' on a mail which is being received from outside the company. That's obviously bogus if you know the first thing about email. Just set up an outside email address (@linkedin.com or @alumni.youruniversity.edu or a vanity domain, or even certain restricted mailing/distribution lists) to point at someone's @example.com mailbox, and you'll see it happening.

The company email is wrongly and stupidly configured. And do they really not provide you with any way to send authenticated email through their servers while you're outside the company? No authenticated SMTP? No VPN? No ActiveSync? I'm not sure I believe it.

If you *really* have to work around this utter brokenness on the part of your idiotic employer, then don't infer the reverse-path automatically from whatever hostname happens to have been set by DHCP today. Use a configuration option with a hard-coded override for the reverse-path address, instead.

But seriously, since you're sending this through your *own* MTA and you're insisting that of course this is a valid thing to do because you do *have* your own MTA and it's set up to receive messages to the address you're using... why in $DEITY's name don't you just set the reverse-path as you with *in* the MTA instead, rather than hacking Evolution to do it?
Comment 35 David Woodhouse 2013-04-08 16:48:16 UTC
To clarify: I object strongly to a boolean option which would use the local username at the local hostname as the SMTP reverse-path. That is almost never the right thing to do.

However, I'd tolerate a string option which is used to override the SMTP reverse-path for a given account with a specific user-provided string. Although it's rare that this would be useful, at least it's not actively encouraging users to do horribly broken things.

The *only* time the boolean option would be sane is when the hostname is actually constant anyway, because you're running on a host with a public IP address and a *constant* public DNS hostname (even if it's dyndns). So a constant string should be perfectly sufficient to work around the misconfiguration of fta's corporate email servers.
Comment 36 Milan Crha 2013-04-09 10:14:55 UTC
(In reply to comment #35)
> However, I'd tolerate a string option which is used to override the SMTP
> reverse-path for a given account with a specific user-provided string.

I consider the part "for a given account" crucial, thus the string property should not be just an email address, but an address which will replace user-configured account's email into a new value for the FROM address.
I think a string value of format
   <old-email>:<new-email>
and replacing only if "<old-email>" matches the currently used FROM and the "<new-email>" is not empty (and possibly some email format checking, like at least the '@' is included).

An example value would be:
   me@company.com:me@home.com
while my Account email address configured in evolution will be me@company.com.
Comment 37 Milan Crha 2013-04-10 10:43:21 UTC
David just notified my on IRC that my above comment #36 is not correct. I added it due to my misunderstanding of David's proposal. After a brief clarification on IRC the setting should be added into CamelSmtpSettings, and will be used in
   eds/camel/providers/smtp
only. This will be accessible in a corresponding .source file in
   ~/.config/evolution/sources
Comment 38 David Woodhouse 2013-04-10 13:09:36 UTC
In fact it might be nice to set and use that setting in *all* cases, rather than grubbing around in the cosmetic Resent-From: and From: headers for it.
Comment 39 Matthew Barnes 2013-12-19 14:34:55 UTC
Closing as WONTFIX since the patch broke Evolution for both Milan and I, and David gave a pretty solid argument against it.
Comment 40 Fabien Tassin 2013-12-19 15:48:48 UTC
@mbarnes: I don't see how my last patch could break evolution for anyone as it's only a gsetting pref, disabled by default, and it's not even exposed in the UI.

I initially wanted to work on yet-another-version of a fix/workaround implementing David's proposal in comment #35, but soon after, comment #37 proposed yet another way to do it, and it exceeds my current knowledge of Camel & Evo's internals.
Comment 41 David Woodhouse 2013-12-19 20:09:43 UTC
I don't think comment #37 was "another way to do it". It was more of a technical clarification of *how* one would implement what was suggested in comment #35.

If you're going to do an option that allows you to specify the SMTP reverse-path to use for a given account's SMTP sessions, it is the file in .config/evolution/sources that would contain it.