SEND(1)

πŸ’– SEND(1) πŸ’–

General Commands Manual Β· SEND(1)

bestie, welcome to the group chat for send(1) β€” the nmh command that takes your draft and actually sends it. It's giving main character energy for outgoing mail. πŸ’Œ


🌸 NAME 🌸

send β€” send an nmh message


✨ SYNOPSIS ✨

send [-help] [-version] [-alias aliasfile] [-draft] [-draftfolder
     +folder] [-draftmessage msg] [-nodraftfolder] [-filter filterfile]
     [-nofilter] [-format | -noformat] [-forward | -noforward] [-mime |
     -nomime] [-msgid | -nomsgid] [-messageid localname | random] [-push
     | -nopush] [-verbose | -noverbose] [-watch | -nowatch] [-mts smtp |
     sendmail/smtp | sendmail/pipe] [-sendmail program] [-server
     servername] [-port port-name/number] [-sasl] [-nosasl] [-saslmech
     mechanism] [-authservice service] [-snoop] [-user username] [-tls]
     [-initialtls] [-notls] [-certverify] [-nocertverify] [-width
     columns] [file ...]

πŸ’« DESCRIPTION πŸ’«

Okay so first thing: send takes each file you name and delivers it to every destination in the To:, cc:, Bcc:, Dcc:, and Fcc: fields of the message. If send is re-distributing a message β€” like when dist invokes it β€” then it looks at the matching Resent-xxx fields instead. πŸ’…

By default, send hands the actual delivery off to the program post, but you can change that by defining the postproc profile component. Lowkey, most of the features people credit to send are actually post doing the work. Not me exposing the truth. πŸ™ˆ

Before send gives the message to post, it runs the message through mhbuild to do any necessary MIME encoding. You can change that with the buildmimeproc profile component. mhbuild gets invoked with the -auto switch, so mhbuild directives are not processed by default. Peep mhbuild(1) for more. ✨

mhbuild scans the draft for a header named Attach. If it finds one or more matches, the draft gets converted into a MIME message. This conversion happens before all other processing. whatnow(1) is where the user interface for managing MIME attachments through this mechanism is described. πŸŽ€

The first part of the MIME message is the draft body β€” but only if that body contains any non-blank characters. The body of each Attach header field is read as a file name, and every file named gets included as a separate part in the MIME message. It's giving assemble-the-avengers. πŸ¦‹

How the content MIME type gets figured out for each part's Content-Type header depends on how your nmh was configured. If a program was found β€” like file with a --mime or -i option β€” that can specify a file's type as a MIME type string, then that program will be used. Wanna check if your nmh is set up that way? Run mhparam mimetypeproc and see if it shows a non-empty string. πŸ”

If your nmh wasn't configured with a program to specify a file type as a MIME string, then a different method figures out the content-type string. This method also kicks in if the configured mimetypeproc fails to find the MIME type of the content. For file names with dot suffixes, the profile gets scanned for a mhshow-suffix- entry for that suffix. If a match is found, the content-type for the part comes from that profile entry. If there's no match in the user profile, the mhn.defaults profile gets scanned next. If no match is found, or the file doesn't have a dot suffix, the content-type is text/plain if the file contains only ASCII characters, or application/octet-stream if it contains characters outside of the ASCII range. See mhshow(1) for more details and example syntax. πŸ’…

Every attached MIME part contains a Content-Description header that includes the filename, and it adds a Content-Disposition header. Here's an example of MIME part headers for an attachment:

Content-Type: text/plain; name="VERSION"; charset="us-ascii"
Content-Description: VERSION
Content-Disposition: attachment; filename="VERSION"

See mhbuild(1) for the explanation of how the Content-Disposition value is selected. 🫢

If -push is specified, send detaches itself from the user's terminal and does its thing in the background. If it's push'd and the draft can't be sent, then an error message gets sent back to the user using the mailproc. If -forward is given, then a copy of the draft gets attached to that failure notice. Using -push is different from just putting send in the background because the output is trapped and analyzed by nmh. So it's not just vibes β€” it's monitored. πŸ‘‘

If -verbose is specified, send will show you the interactions happening with the transport system, before actual delivery. If -watch is specified, send will monitor the delivery of local and network mail. So if you specify both switches, you can gather a large amount of detail about each step of the message's entry into the transport system. It's giving surveillance, but make it mail. πŸ‘€

The -draftfolder +folder and -draftmessage msg switches invoke the nmh draft folder facility. This is an advanced β€” and highly useful β€” feature. Consult mh-draft(5) for more info. πŸ—‚οΈ

send with no file argument will ask whether the draft is the intended file, while -draft suppresses that question. Once the transport system has successfully accepted custody of the message, the file gets renamed with a site-dependent prefix β€” usually a comma β€” which lets it be retrieved until the next draft message is sent. If there are errors in the formatting of the message, send will abort with a (hopefully) helpful error message. Fingers crossed. 🀞

If a Bcc: field is encountered, its addresses get used for delivery, and the Bcc: field gets removed from the message sent to sighted recipients. The blind recipients will receive an entirely new message with a minimal set of headers. The body of this new message contains a copy of the message sent to the sighted recipients, either marked up with the indicator text "Blind-Carbon-Copy" or encapsulated as a MIME digest. Sneaky but organized. 🀫

If a Dcc: field is encountered and the sendmail/pipe mail transport method is not in use, its addresses get used for delivery, and the Dcc: field gets removed from the message. The blind recipients will receive exactly the same message as the sighted recipients.

WARNING 🚨 Recipients listed in the Dcc: field get no explicit indication that they received a β€œblind copy”. This can cause blind recipients to accidentally reply to all of the sighted recipients of the original message, revealing that they got a blind copy. On the other hand, since a normal reply to a message sent via a Bcc: field will generate a reply only to the sender of the original message, it takes extra effort in most mailers to reply to the included message, so that would usually only be done deliberately, rather than by accident. Be careful bestie, this is not the vibe. πŸ’€

If the sendmail/pipe mail transport method is used, then messages containing a Dcc: field are rejected. Periodt. ❌

If -filter filterfile is specified, then this copy gets filtered β€” re-formatted β€” by mhl before it's sent to the blind recipients. Alternatively, if you specify the -mime switch, then send will use the MIME rules for encapsulation. Choose your fighter. πŸŽ€

Before sending the message, the Date: now field gets appended to the headers in the message. If -msgid is specified, then a Message-ID: field also gets added to the message. Time stamping, slay. ⏰

The -messageid switch selects the style used for the part after the @ in Message-ID:, Resent-Message-ID:, and Content-ID: header fields. The two acceptable options are localname β€” which is the default β€” and random. With localname, the local hostname is used. With random, a random sequence of characters is used instead. Note that the -msgid switch must be enabled for this switch to have any effect. No cap. 🎲

If send is re-distributing a message β€” when invoked by dist β€” then Resent- gets prepended to each of these fields: From:, Date:, and Message-ID:. πŸŒ€

A From: field is required for all outgoing messages. Multiple addresses are permitted in the From: field, but a Sender: field is required in that case. Otherwise, a Sender: field is optional. Rules are rules. πŸ“¬

If a message has multiple From: addresses, doesn't include a Sender: field, but does include an Envelope-From: field, then the Envelope-From: field will be used to construct a Sender: field. Problem solved. πŸ› οΈ

When using SMTP for mail submission, the envelope-from used for the SMTP transaction comes from the Envelope-From: field. If there's no Envelope-From: field, the Sender: field is used. If neither the Envelope-From: nor the Sender: field is present, the From: field is used. And when Envelope-From: appears in a message, it gets removed from the final outgoing message. Bye bestie. πŸ‘‹

By using the -format switch, each entry in the To: and cc: fields gets replaced with β€œstandard” format entries. This standard format is designed to be usable by all of the message handlers on the various systems around the Internet. If -noformat is given, then headers are output exactly as they appear in the message draft. No edits, no notes. πŸ“

If an Fcc: folder is encountered, the message gets copied to the specified folder for the sender in the format it will appear to any non-Bcc receivers of the message. That means it will have the appended fields and field reformatting. The Fcc: fields get removed from all outgoing copies of the message. Archive and yeet. πŸ—ƒοΈ

Beware, bestie: if an Fcc: with one or more folders is present but none of the folders exist, and the default fileproc and postproc are in use, then refile will prompt the user to create the folder(s) if -push is not specified. If all responses are negative, or creation of each folder fails, or -push is specified, the message will not be copied to any folder and will be removed by post. With the default refile switches, the message draft gets renamed according to the specification of its -nolink switch. That's a lot of ifs, but okay. 😭

By using the -width columns switch, you can direct send as to how long it should make header lines containing addresses. Custom width, custom vibe. πŸ“

The mail transport system default is provided in /etc/nmh/mts.conf, but you can override it here with the -mts switch. Defaults are cute until they aren't. βš™οΈ

If nmh is using sendmail/pipe or sendmail/smtp as its mail transport system, the -sendmail switch can be used to override the default sendmail program. Override, slay. πŸ’…

If nmh is riding with the SMTP MTA, then -server and -port are your lil override switches for the default mail server (which is defined by the servers entry in /etc/nmh/mts.conf). And -snoop? That one lets you peek at the whole SMTP transaction. πŸ‘€

Bestie, warning time: that SMTP transaction might contain authentication info, either sitting there in plaintext or in base64 that's basically decodable by anyone with a pulse. Not cute. πŸ™ˆ

Oh and if you're doing -sasl -saslmech xoauth2, the HTTP transaction gets shown too.

If nmh was compiled with SASL support, -sasl and -nosasl turn SASL authentication with the SMTP MTA on and off. Depending on which SASL mechanism you're using, this might hit you with an extra password prompt (but you can stash that password in the netrc file, and mh-profile(5) explains how). -saslmech picks a specific SASL mechanism, and -user picks an authorization userid to hand to SASL that isn't the default one. The credentials profile entry in mh-profile(5) lays out all the ways to supply a username and password. πŸ’…

If SASL authentication goes through, nmh will try to negotiate a security layer for session encryption. When you're watching the SMTP transaction with -snoop, encrypted data gets labelled (encrypted) and (decrypted) β€” and for its other features, go read what post(8) says about -snoop. πŸ”

If nmh was compiled with OAuth support, then -sasl plus -saslmech xoauth2 enables OAuth authentication. -user is mandatory here, and the username has to be an email address you actually have for that service, which you specify with the -authservice service switch. Before you can use OAuth authentication, you gotta authorize nmh by running mhlogin and granting authorization to that account. mhlogin(1) has the whole story. ✨

If nmh was compiled with TLS support, -tls and -initialtls will require TLS negotiation when connecting to the SMTP MTA. -tls negotiates TLS as part of the normal SMTP protocol using the STARTTLS command. -initialtls negotiates TLS immediately after the connection happens, before any SMTP commands go out or come in. When you're watching the SMTP transaction with -snoop, encrypted data gets labelled (tls-encrypted) and (tls-decrypted) β€” again, post(8)'s description of -snoop covers its other features. And -notls disables every attempt to negotiate TLS. πŸ¦‹

If port 465 is specified and none of the TLS switches were enabled, -initialtls gets implied, as long as TLS support was compiled in. So real talk: port 465 for SMTPS (SMTP over SSL) was deregistered by IANA back in 1998, but it's still used for that service. Iconic behaviour, honestly. πŸ’€

When you're using TLS, the default is to verify the remote certificate and SubjectName against the local trusted certificate store. -certverify and -nocertverify control this. Peep your OpenSSL documentation for more on certificate verification. πŸŽ€

The files named by the β€œAliasfile:” profile entry β€” plus any additional alias files you pass with the -alias aliasfile switch β€” will be read (and yes, you can name more than one file, each one preceded by -alias). mh-alias(5) has more. πŸ“š


🌸 Selection based on sender address: sendfrom 🌸

You can use one or more sendfrom profile components to select a mail server address, a mail server port, or literally any other switch that can be supplied to post. The way it works: first it looks at the sender address and domain name in the message draft, as described below. Then it hunts for a corresponding profile entry, which contains the post switches. To enable it, add profile entries shaped like this:

sendfrom-address/domain name: post switches

The email address gets extracted from the Envelope-From: header β€” if that's not blank β€” then the Sender: header, then the From: header line in the message draft. Multiple profile entries with different email addresses or domain names are supported, which means you can attach different switches to post, like -user, to different email addresses. And if you use a domain name, it matches every user in that domain. πŸ’«

Here's an example profile entry for using the SMTP on the localhost when the sender address is clearly local:

sendfrom-localuser@localhost: -server localhost -port smtp

(That indentation means a continued line, which MH profiles support.) Oh, and the username doesn't have to be the same as the sender address that was extracted from the appropriate header line as noted above.

Here are example profile entries that use an nmh credentials file:

credentials: file:nmhcreds
sendfrom-sendgrid_address@example.com: -sasl -tls
     -server smtp.sendgrid.net
sendfrom-outbound.att.net: -sasl -initialtls
     -server outbound.att.net -port 465
sendfrom-fastmail.com: -initialtls -sasl -saslmech LOGIN
     -server smtps-proxy.messagingengine.com -port 80

where nmhcreds lives in the user's nmh directory (from the Path profile component) and contains:

machine smtp.sendgrid.net
     login sendgrid_login@example.com
     password ********
machine outbound.att.net
     login att_login@example.com
     password ********
machine smtps-proxy.messagingengine.com
     login fastmail_login@example.com
     password ********

For more info on authentication to mail servers, check mhlogin(1) for OAuth services, and mh-profile(5) for login credentials. 🫢


✨ FILES ✨

  • $HOME/.mh_profile β€” The user profile

πŸ’– PROFILE COMPONENTS πŸ’–

  • Path: β€” To determine the user's nmh directory
  • Aliasfile: β€” For a default alias file
  • Signature: β€” To determine the user's mail signature
  • mailproc: β€” Program to post failure notices
  • postproc: β€” Program to post the message
  • sendfrom-address: β€” Switches to post for sender address
  • sendfrom-domain: β€” Switches to post for sender domain name

🌈 SEE ALSO 🌈

comp(1), dist(1), file(1), forw(1), mhbuild(1), mhparam(1), mhlogin(1), refile(1), repl(1), whatnow(1), mh-alias(5), mh-profile(5), mh-tailor(5), post(8)


πŸ‘‘ DEFAULTS πŸ‘‘

  • `file' defaults to <mh-dir>/draft
  • `-alias' defaults to /etc/nmh/MailAliases
  • -nodraftfolder
  • -nofilter
  • -format
  • -forward
  • -nomime
  • -nomsgid
  • -messageid localname
  • -nopush
  • -noverbose
  • -nowatch
  • -width 72
  • -certverify

⭐ CONTEXT ⭐

None


πŸ’€ BUGS πŸ’€

Under some configurations, it is not possible to monitor the mail delivery transaction; -watch is a no-op on those systems.


And that's the whole page, bestie β€” you made it to the end! πŸŽ‰ This was nmh-1.8, dated 2022-12-22, for SEND(1). Now go send that mail. πŸ’…πŸ’–

πŸ“¦ where this page comes from