Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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?

share|improve this question

migrated from stackoverflow.com Jun 22 '11 at 6:21

This question came from our site for professional and enthusiast programmers.

7 Answers 7

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

share|improve this answer
+1. Wonderfully detailed. –  Noufal Ibrahim Jun 23 '11 at 15:20
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 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

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

share|improve this answer
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
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

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
share|improve this answer
That doesn't acually use mail. –  user16144 Oct 17 '12 at 19:09
@user16144 No, but it's a nice alternative that the OP might like to consider. –  trusktr Feb 12 '14 at 3:24

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

share|improve this answer

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.

share|improve this answer

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

share|improve this answer
cat htmlfile.html | mail -s "subject" xx@example.com
share|improve this answer
Nope. This will send a text email with HTML in the body. –  Noufal Ibrahim Jun 22 '11 at 6:35

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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