mail -s "subject" xxxxx@gmail.com <test.html works, but only for plain text email.

What is the correct way to send HTML email using the Linux command mail?


There are many different versions of mail around. When you go beyond mail -s subject to1@address1 to2@address2 <body (for sending, that's all POSIX guarantees — and even -s didn't exist in the old days), they tend to have different command line options. Adding an additional header isn't always easy.

  • With some mailx implementations, e.g. from mailutils on Ubuntu or Debian's bsd-mailx, it's easy, because there's an option for that.

    mailx -a 'Content-Type: text/html' -s "Subject" to@address <test.html
  • With the Heirloom mailx, there's no convenient way. One possibility to insert arbitrary headers is to set editheaders=1 and use an external editor (which can be a script).

    ## Prepare a temporary script that will serve as an editor.
    ## This script will be passed to ed.
    cat <<'EOF' >>"$temp_script"
    Content-Type: text/html
    $r test.html
    ## Call mailx, and tell it to invoke the editor script
    EDITOR="ed -s $temp_script" heirloom-mailx -S editheaders=1 -s "Subject" to@address <<EOF
    rm -f "$temp_script"
  • With a general POSIX mailx, I don't know how to get at headers.

If you're going to use any mail or mailx, keep in mind that

  • This isn't portable even within a given Linux distribution. For example, both Ubuntu and Debian have several alternatives for mail and mailx.
  • When composing a message, mail and mailx treats lines beginning with ~ as commands. If you pipe text into mail, you need to arrange for this text not to contain lines beginning with ~.

If you're going to install software anyway, you might as well install something more predictable than mail/Mail/mailx. For example, mutt. With Mutt, you can supply most headers in the input with the -H option, but not Content-Type, which needs to be set via a mutt option.

mutt -e 'set content_type=text/html' -s 'hello' 'to@address' <test.html

Or you can invoke sendmail directly. There are several versions of sendmail out there, but they all support sendmail -t to send a mail in the simplest fashion, reading the list of recipients from the mail. (I think they don't all support Bcc:.) On most systems, sendmail isn't in the usual $PATH, it's in /usr/sbin or /usr/lib.

cat <<'EOF' - test.html | /usr/sbin/sendmail -t
To: to@address
Subject: hello
Content-Type: text/html

  • Tried using the mutt example above; substituting real values for the filename, to email address, etc. but got "No recipients were specified" I'm very new to mutt, @Gilles do you know why that might have happened? (osx mountain lion, mutt 1.5.21 installed via homebrew) – Chuck van der Linden Jul 15 '13 at 16:58
  • my second line was "To: myaddress@mycompany.com" (sorry for lack of formatting, not possible in a response, actual text was sans quotes) and I included a blank line before putting in the EOF. would there be configuration I need to do to mutt? prior to trying the example you gave (with proper values substituted) all I did was 'brew install mutt' – Chuck van der Linden Jul 15 '13 at 19:10
  • @ChuckvanderLinden Ask a new question. Copy-paste the exact command you ran and the full error message. See if you can send an email from mutt using the interactive interface. – Gilles 'SO- stop being evil' Jul 15 '13 at 19:15
  • I was able to send something via the 'interactive' interface, it initially complained about a mail directory missing and offered to create it. reminded how much I hate vim ;-) but got it to send. I'll start a new question as that is easier to format etc. The exact error message was just what I said "No recipients were specified." – Chuck van der Linden Jul 15 '13 at 19:45

echo "To: me@example.com"
echo "Subject: hello"
echo "Content-Type: text/html"
echo "<html><b><font size='7'>H</font>ello</b></html>"
) | /usr/sbin/sendmail -t
  • 7
    That doesn't acually use mail. – user16144 Oct 17 '12 at 19:09
  • 4
    @user16144 No, but it's a nice alternative that the OP might like to consider. – trusktr Feb 12 '14 at 3:24
  • Yes, it does not use mail but it works everywhere I have tried it which is more than I can say for the other solutions. – user1683793 May 3 '18 at 16:21
  • Works beautifully on Mac as well. – Asim Jalis Feb 28 '19 at 20:41

With the Heirloom mailx, convenient way is

mailx -s "$(echo -e "Newsletter issue 3\nContent-Type: text/html")" user@server.com < /tmp/htmlmail.txt

Thanks, Dude
Tested on Fedora 17, and worked

  • 1
    Cheeky. I like it. :-] – Alastair Irvine Nov 16 '16 at 16:29
  • 1
    Beware that this solution may lead to the email having both "Content-Type: text/html" and "Content-Type: text/plain", and potential inconsistencies if you use this way to specify charset. – Skippy le Grand Gourou Mar 16 '17 at 15:45

You will have to add Content-Type header to your email to make this happen.

echo "<html><b>Hello</b></html>" | mail -a "Content-type: text/html;" -s "Testing" me@example.com

will work

  • 2
    mail: illegal option -- a – pyth0ner Jun 22 '11 at 6:56
  • Do you have mailx? That might have the option. If that doesn't work. If that doesn't work, you can consider using mutt although I don't know off hand what the command line switches to do it are. – Noufal Ibrahim Jun 22 '11 at 7:04
  • 1
    if mail isn't cutting the mustard, use python ... docs.python.org/library/email-examples.html examples is the 3rd one or #6 which suits your requirement. – sdolgy Jun 22 '11 at 8:40
  • Python will require you to write (and maintain) a script. A command line one liner has different advantages. – Noufal Ibrahim Jun 22 '11 at 11:04
  • I have mailx,but "option -a" don't work,still show:mail: illegal option -- a – pyth0ner Jun 27 '11 at 1:17

With heirloom-mailx you can change sendmail program to your hook script, replace headers there and then use sendmail.

The script I use (~/bin/sendmail-mailx-hook):


sed '1,/^$/{
s,^\(Content-Type: \).*$,\1text/html; charset=utf-8,g
s,^\(Content-Transfer-Encoding: \).*$,\18bit,g
}' | sendmail $@

This script changes the values in the mail header as follows:

  • Content-Type: to text/html; charset=utf-8
  • Content-Transfer-Encoding: to 8bit (not sure if this is really needed).

To send HTML email:

mailx -Ssendmail='~/bin/sendmail-mailx-hook' -s "subject" xxxxx@gmail.com < test.html

This method is more effective than proposed by @Gilles because it does not create temporary files and just fix the stream on-the-fly.


I have used the below scripts to happen


echo "To: yourmail@domain.com"
echo "Subject: Job Status"
echo "Content-Type: text/html"
echo "<html>
<title>Status of the jobs during the day</title>
table, th, td {
    border: 1px solid blue;
    border-collapse: collapse;
th, td {
    padding: 5px;
<table style='width:100%'>
<tr bgcolor='#808080'>
    <th>Job Name</th>
    <th>System name</th>
) | /usr/sbin/sendmail -t

For me i needed to specify a variable such as SMTP server, so the mail command worked in the below fashion. I searched across many posts, and i found below property to convert the body into text/html. Now the email i receive is in the HTML format.

Content-Disposition: inline

Unix version: Red Hat Enterprise Linux Server release 6.6 (Santiago)

First. Create whatever information is needed into a script (testSql.sh)

echo "<html><body><pre>"
mysql -u USERNAME -pPASSWORD -P PORTNUMBER -h HOSTNAME DBNAME --table -e "select columns from tablename where member in ('value1','value2')"
echo "</pre></body></html>"

Second. Pipe that script to the mail command

./testSql.sh  | mail -v -S smtp=smtp://IP:PORTNUMBER -s "$(echo -e "This is the subject\nContent-Type: text/ht ml\nMIME-Version: 1.0\nContent-Disposition: inline")" userid@email.com

By doing this i get information as below in the email:

Content-Disposition: inline Message-ID: User-Agent: Heirloom mailx 12.4 7/29/08 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit 

Value1 Value2

Value1 and Value2 as per the HTML tagging done in the testSql.sh

  • i needed \r\n on my Centos-8 – edwardsmarkf Jan 12 at 15:49

Posted in another thread but basically on our version of mail/mailx(12.5+) the -a parameter for mail doesn't work anymore since it adds an attachment and I couldn't find any replacement parameter for additional headers so the easiest way for me was to use sendmail.

Below is a simple 1 liner I created to run in our bash script that works for us. It just basically passes the Content-Type: text/html, subject, and the body and works.

printf "Content-Type: text/html\nSubject: Test Email\nHTML BODY<b>test bold</b>" | sendmail <Email Address To>

If you wanted to create an entire html page from a variable an alternative method I used in the bash script was to pass the variable as below.

emailBody="From: <Email Address From>
Subject: Test
Content-Type: text/html; charset=\"us-ascii\"
<b> test bold</b>

echo "$emailBody" | sendmail <Email Address To>
cat htmlfile.html | mail -s "subject" xx@example.com
  • 5
    Nope. This will send a text email with HTML in the body. – Noufal Ibrahim Jun 22 '11 at 6:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.