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?

9 Answers 9


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) Jul 15, 2013 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' Jul 15, 2013 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. Jul 15, 2013 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." Jul 15, 2013 at 19:45
  • New question unix.stackexchange.com/questions/83137/… Jul 15, 2013 at 20:06

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, 2012 at 19:09
  • 4
    @user16144 No, but it's a nice alternative that the OP might like to consider.
    – trusktr
    Feb 12, 2014 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. May 3, 2018 at 16:21
  • Works beautifully on Mac as well.
    – Asim Jalis
    Feb 28, 2019 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. :-] Nov 16, 2016 at 16:29
  • 2
    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. Mar 16, 2017 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

  • 3
    mail: illegal option -- a
    – pyth0ner
    Jun 22, 2011 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. Jun 22, 2011 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, 2011 at 8:40
  • Python will require you to write (and maintain) a script. A command line one liner has different advantages. Jun 22, 2011 at 11:04
  • I have mailx,but "option -a" don't work,still show:mail: illegal option -- a
    – pyth0ner
    Jun 27, 2011 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 Jan 12, 2021 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. Jun 22, 2011 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.