Author Topic: Need a little help SMTP email send program syntax, terminating string.  (Read 2476 times)

0 Members and 1 Guest are viewing this topic.

Offline zilp

  • Frequent Contributor
  • **
  • Posts: 329
  • Country: de
If you are sending a message to recipient@example.com from account@domain, the client should:
  • Connect to the SMTP server using the appropriate port, and wait for a response.  The response should be 220.
  • Send "EHLO domain\r\n", and wait for a response.  The response should be 220.
Servers will check domain against the list of domains the specified username is allowed to send, and will reject the MAIL FROM command if they do not match.  In the case where the server knows about domain users, it may even check that username and account match.  So, you cannot just use whatever domain in a EHLO greeting!

This is not correct. The name specified in the EHLO has absolutely nothing to do with the email addresses of the submitted email, it is supposed to be the host name of the system submitting the email, or an IP literal in case the host name is unknown:

https://datatracker.ietf.org/doc/html/rfc5321#section-4.1.1.1

In practice, for submission connections, servers will accept anything that is syntactically valid, because in practice, most SMTP submission clients nowadays can't really send anything particularly meaningful anyway (end user devices usually don't have DNS names, and often are behind NAT and thus at best know their RFC1918 address on the random LAN that the happen to be connected to).

Servers often will check that the account is allowed to use the source address, but that is only based on the authentication credentials. Also, if you were to use TLS, servers might use SNI to distinguish accounts (so that you can have the same account name for distinct accounts of different mail serever names hosted on the same physical server and the same IP addresses).

  • Send "AUTH LOGIN\r\n", and wait for a response.  The response should be 334.
  • Send "username\r\n" (where username is Base64-encoded form of the username), and wait for a response.  The response should be 334.
  • Send "password\r\n" (where password is Base64-encoded form of the password), and wait for a response.  The response should be 235.

For one, technically, you would first have to check in the EHLO response which authentication mechanisms are supported. Of course, if you only support one anyway, I guess you might as well just try that one.

But also,  LOGIN is obsoleted, and the non-obsolete plain-text mechanism, PLAIN, makes things quite a bit simpler, because you send username and password in one auth string, which then also can be supplied as the initial-response in the AUTH command itself, so there is no need to handle the command continuation.

  • Send message body.  If the body is not empty, it must end with "\r\n".
  • Send ".\r\n", and wait for a response.  The response should be 250.

I guess it should be noted that if a line of the message body starts with a '.', then you have to double that to '..', or else your mail might get corrupted (and, depending on the circumstances, you might have a security problem).
 

Offline JesterTopic starter

  • Frequent Contributor
  • **
  • Posts: 883
  • Country: ca
Code: [Select]
  espClient.println(F("DATA"));
  espClient.println(F("To: <info@*****.com>"));
  espClient.println(F("From: <info@*****.com>"));
  espClient.println(F("Content-Type: text/plain; charset=UTF-8"));
  espClient.println(F("Subject: 8266 sender message 2024"));
  espClient.println();
  espClient.println(F("8266 sender message 2024"));

Obviously, you can't include a "Date" header if you have no clock or calendar facility on the Arduino, so that can be omitted. And of course, as others have mentioned, you need a blank line between headers and body of the message. (BTW, if memory serves, I think println() can be used without arguments to emit just line break characters - no need to pass an empty string.) I won't go into the mess that is other content types and MIME message formatting. ;D

Note that the Content-Type header in the syntax used here is a MIME-Header, and as such, if you use it, you also have to add a MIME-Version header:

https://datatracker.ietf.org/doc/html/rfc2045#section-4

Also, you have to include a Date header, it is mandatory in RFC5322:

https://datatracker.ietf.org/doc/html/rfc5322#section-3.6

It's probably just a matter of time before this will stop working (again) as they keep "uppping" the requirements, however for now it's working.
Funny how you guys can diagnose and solve a problem from half way around the world, but the actual email provider can't.

Made my day guys/gals
« Last Edit: July 27, 2024, 08:29:17 am by Jester »
 

Offline zilp

  • Frequent Contributor
  • **
  • Posts: 329
  • Country: de
It's probably just a matter of time before this will stop working (again) as they keep "uppping" the requirements, however for now it's working.

If you follow the standards, things should essentially never break.

Funny how you guys can diagnose and solve a problem from half way around the world, but the actual email provider can't.

Well, the fact that they accept connections without TLS at all kinda already tells you that you maybe should be looking for a different provider, I guess. Though then this client wouldn't work any more, of course ...
 
The following users thanked this post: Jester

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6715
  • Country: fi
    • My home page and email address
In practice, for submission connections, servers will accept anything that is syntactically valid [in EHLO domain], because in practice, most SMTP submission clients nowadays can't really send anything particularly meaningful anyway (end user devices usually don't have DNS names, and often are behind NAT and thus at best know their RFC1918 address on the random LAN that the happen to be connected to).
Yes, the RFC mandates that SMTP servers don't reject messages just because they don't like the EHLO command, but practice trumps RFC.

But, for a local IoT server implementing a mail transfer agent, forwarding the messages to the appropriate mail servers, it really should verify the client IP address matches the local address, the EHLO domain is either that same IP address or a matching domain name that matches the filter set in e.g. Exim auth_advertise_hosts, or otherwise your IoT server may be exploitable to forward spam by the ton because the IoT appliances source code revealed the username and password.

I've mostly been on the other side of this, configuring mail transfer agents on servers, so I definitely "err" on the safe side here.  You do not want your IoT device firmware to reveal how to use the related SMTP servers as spam relays; trust me on this.

Hmm.. for a better EHLO advice, I think using either the configured (host and) domain name, or the IP address if unknown or not configured, would work best.  This way, if the mail provider requires something here, the user can configure their IoT box to comply.

For one, technically, you would first have to check in the EHLO response which authentication mechanisms are supported. Of course, if you only support one anyway, I guess you might as well just try that one.

But also,  LOGIN is obsoleted, and the non-obsolete plain-text mechanism, PLAIN, makes things quite a bit simpler, because you send username and password in one auth string, which then also can be supplied as the initial-response in the AUTH command itself, so there is no need to handle the command continuation.
Fully agreed.

I guess it should be noted that if a line of the message body starts with a '.', then you have to double that to '..', or else your mail might get corrupted (and, depending on the circumstances, you might have a security problem).
Yep, true.



I guess a better suggestion for sending email from an IoT device would be:
  • Connect to the SMTP server using the appropriate port, and wait for a response.  The response should be 220.
  • Send "EHLO client\r\n", and wait for a response.  The response should be 220.
    The response text contains "AUTH" followed by whitespace-separated authentication methods, which should include "PLAIN".
  • Send "AUTH PLAIN creds\r\n", and wait for a response.  The response should be 235.
    Try not to hardcode creds in your firmware, and instead treat it as a (privileged) configuration string.
  • Send "MAIL FROM:<sender>\r\n", and wait for a response.  The response should be 250.
  • Send "RCPT TO:<recipient>\r\n", and wait for a response.  The response should be 250.
  • Send "DATA\r\n", and wait for a response.  The response should be 354.
  • Send each header line, for example "Subject: This is the message subject\r\n".  (Every header line must end with "\r\n".)
  • Send empty line between headers and message body, "\r\n".
  • Send message body.  If a line begins with a ., it should be doubled (to ..).  If the body is not empty, it must end with "\r\n".
  • Send ".\r\n", and wait for a response.  The response should be 250.
  • Send "QUIT\r\n", and wait for a response.  The response should be 221.
where host is the fully-qualified host name if configured, or the IP address if not configured; creds is Base64 encoded username followed by an ASCII null character followed by the password; sender is the sender mail address matching creds (and host if the SMTP server does strict EHLO checking); and recipient is the recipient mail address.

RFC 5322 describes message headers you can use, and how those headers and body can be formatted.
 
The following users thanked this post: Jester

Offline quadtech

  • Regular Contributor
  • *
  • Posts: 68
  • Country: in
If your environment allows, it would be preferable to use a local mail relay host to which the IOT device talks,
and the mail relay host  (for ex - linux running postfix/sendmail etc) is the one which actually talks to the ISP mail gateway. That would allow setting up TLS etc on the relay host to the external mail gateway.
« Last Edit: July 27, 2024, 02:08:15 pm by quadtech »
 
The following users thanked this post: Jester

Offline zilp

  • Frequent Contributor
  • **
  • Posts: 329
  • Country: de
Yes, the RFC mandates that SMTP servers don't reject messages just because they don't like the EHLO command, but practice trumps RFC.

No, it doesn't. Submission servers generally do not check, because there is nothing that they could check. Your average MUA behind NAT has no real hostname to send, and has an RFC1918 address that the server can not see, and doesn't know what IP address the server sees. So, at best, they could, following the RFC, send an IP literal with that RFC1918 address. And what is the server supposed to do with that? There is no way for the server to know whether that is actually the IP address of the device. It obviously won't match the remote address on the TCP socket. Checking against the remote address on the TCP socket makes no sense either, because the MUA doesn't know that address so that it could send it in the HELO/EHLO.

I think one could say that it has developed a conensus of sorts that the best practice is to send a localhost IP literal ('[127.0.01]') in submission EHLO. That seems to work even with rare weird servers that do have some restrictions on permissible EHLO parameters, is perfectly RFC compliant, and also doesn't leak any information (like local IP addresses, say).

Things are different with server-to-server connections, but that is not what this thread is about.

But, for a local IoT server implementing a mail transfer agent, forwarding the messages to the appropriate mail servers, it really should verify the client IP address matches the local address, the EHLO domain is either that same IP address or a matching domain name that matches the filter set in e.g. Exim auth_advertise_hosts, or otherwise your IoT server may be exploitable to forward spam by the ton because the IoT appliances source code revealed the username and password.

Are you talking about a outbound relay accepting mails from IoT devices on the local network?! That certainly should ignore the EHLO parameter. How you should do client authentication in that case depends on the circumstances, but EHLO is irrelevant for that. Using auth_advertise_hosts for that doesn't make a whole lot of sense, though. Either you have actual (per-device provisioned) credentials, then, there is no point limiting authentication based on IP addresses, or you don't, then you can just skip the SMTP AUTH part completely and just use ACLs to limit relaying to specific IP prefixes.

Hmm.. for a better EHLO advice, I think using either the configured (host and) domain name, or the IP address if unknown or not configured, would work best.  This way, if the mail provider requires something here, the user can configure their IoT box to comply.

Really, an email provider that didn't accept [127.0.0.1] wouldn't work with a lot of MUAs out there already, so there really is no need to make things configurable.
 
The following users thanked this post: Jester

Offline gmb42

  • Frequent Contributor
  • **
  • Posts: 297
  • Country: gb
If you're looking for a test SMTP server on Windows (and other OSs) I would recommend smtp4dev
 

Offline peter-h

  • Super Contributor
  • ***
  • Posts: 3947
  • Country: gb
  • Doing electronics since the 1960s...
How different would the foregoing be with a fairly modern smtp auth service such as authsmtp.com? These also do nowadays pretty much essential stuff like DKIM. Google is now dumping all incoming mail unless it has either SPF (which is not easy to keep valid over time) or DKIM.

The connection can be plain text username and pwd; no need for TLS.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline zilp

  • Frequent Contributor
  • **
  • Posts: 329
  • Country: de
How different would the foregoing be with a fairly modern smtp auth service such as authsmtp.com? These also do nowadays pretty much essential stuff like DKIM. Google is now dumping all incoming mail unless it has either SPF (which is not easy to keep valid over time) or DKIM.

I have no idea what you mean by "smtp auth service". authsmtp.com seem to be an email outbound provider!?

As for DKIM and SPF, that's something that almost all email providers support nowadays, and also, it is not difficult to "keep SPF valid". Actually, there is nothing to keep valid about it, as long as your outbound servers don't change, SPF doesn't need to change either, and if your email provider changes the servers, they should take care of changing SPF, too.

The connection can be plain text username and pwd; no need for TLS.

With any reasonable email provider, that really shouldn't be supported anymore. Though no idea what you are trying to say here, really.
 

Offline peter-h

  • Super Contributor
  • ***
  • Posts: 3947
  • Country: gb
  • Doing electronics since the 1960s...
That's a fairly usual reply tone from you zilp.

Yes of course authsmtp.com are an outbound email provider.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf