Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I prepared the following macros to format e-mail adresses in a e-mail header.

\usepackage{xifthen}% Provides \ifthenelse and \isempty

% E-Mail header strings with format.
\newcommand{\fromString}{\textbf{From:} }
\newcommand{\toString}{\textbf{To:} }

% E-Mail with or without alias.
\newcommand{\email}[2][]{%
    \ifthenelse{\isempty{#1}}%
        {<#2>}% E-Mail only
    {"#1" <#2>}% Alias and E-Mail
}

% E-Mail header From:    
\newcommand{\emailFrom}[2][]{%
    \ifthenelse{\isempty{#1}}%
        {\fromString \email{#2}\\}% E-Mail only
    {\fromString \email[#1]{#2}\\}% Alias and E-Mail
}

% E-Mail header To:
\newcommand{\emailTo}[2][]{%
    \ifthenelse{\isempty{#1}}%
        {\toString \email{#2}\\}% E-Mail only
    {\toString \email[#1]{#2}\\}% Alias and E-Mail
}

The macros can be used as illustrated by the following examples. Please mind that [] are used for optional arguments instead of {}.

\email[Doe, John]{john.doe@stackexchange.com}
\emailFrom[Doe, John]{john.doe@stackexchange.com}
\emailFrom{john.doe@stackexchange.com}
\emailTo[Doe, John]{john.doe@stackexchange.com}
\emailTo{john.doe@stackexchange.com}

The formatted output looks like this:

"Doe, John" <john.doe@stackexchange.com>
From: "Doe, John" <john.doe@stackexchange.com>
From: <john.doe@stackexchange.com>
To: "Doe, John" <john.doe@stackexchange.com>
To: <john.doe@stackexchange.com>

How could I extend the macro so that I can use it with multiple e-mail addresses? The following example should explain the issue. As you can see by the third example, the occurance of the alias is individual for each e-mail entry.

To: "Doe, John" <john.doe@stackexchange.com>, "Doe, Jane" <jane.doe@stackexchange.com>
To: <john.doe@stackexchange.com>, <jane.doe@stackexchange.com>
To: <john.doe@stackexchange.com>, "Doe, Jane" <jane.doe@stackexchange.com>

Since I am new to using macros in latex you are also welcome to generally improve my commands or leave comments to do so.


Update:

While working with several email I realized that it can also happen, that there is no email address given, only the email alias. This happens when someone forwards emails e.g., as an internal conversation in a company. Nevertheless, I accept this format as a valid email header. Do you see any chance to include this schema in the macros? Here is an example.

From: John Doe
Subject: Re: E-Mail headers
Date: Wed, 22 Aug 2012 23:42:00 +0200
To: Jane Doe
share|improve this question
add comment

2 Answers

up vote 6 down vote accepted

I'd use a different syntax for the cases of one address and multiple addresses:

\documentclass{article}
\usepackage[T1]{fontenc}
\makeatletter
\newif\if@emailenv
\newenvironment{emails}[1][\ignorespaces]
  {\set@email@separator{#1}\@emailenvtrue\begin{flushleft}}
  {\end{flushleft}}
\def\set@email@separator#1{%
  \def\email@separator{#1\def\email@separator{,}}}
\newcommand{\@email}[2][]{%
  \if@emailenv\else\begin{flushleft}\fi
  \email@separator\space
  \if\relax\detokenize{#1}\relax\else"#1" \fi
  \texttt{<#2>}%
  \if@emailenv\ignorespaces\else\end{flushleft}\fi
}
\newcommand{\email}{%
  \if@emailenv\else\set@email@separator{\ignorespaces}\fi\@email}
\newcommand{\emailTo}{%
  \if@emailenv\else\set@email@separator{\textbf{To:}}\fi\@email}
\newcommand{\emailFrom}{%
  \if@emailenv\else\set@email@separator{\textbf{From:}}\fi\@email}
\newcommand{\emailsFrom}{\emails[\textbf{From:}]}
\newcommand{\emailsTo}{\emails[\textbf{To:}]}
\let\endemailsFrom\endemails
\let\endemailsTo\endemails
\makeatother

\begin{document}
\email{pippo@stackexchange.com}

\email[Doe, John]{john.doe@stackexchange.com}

\emailTo{pippo@stackexchange.com}

\emailTo[Doe, John]{john.doe@stackexchange.com}

\emailFrom{pippo@stackexchange.com}

\emailFrom[Doe, John]{john.doe@stackexchange.com}



\begin{emails}
\email{pippo@stackexchange.com}
\email[Doe, John]{john.doe@stackexchange.com}
\email[Doe, Jane]{jane.doe@stackexchange.com}
\end{emails}

\begin{emailsTo}
\email{pippo@stackexchange.com}
\email[Doe, John]{john.doe@stackexchange.com}
\email[Doe, Jane]{jane.doe@stackexchange.com}
\end{emailsTo}

\begin{emailsFrom}
\email{pippo@stackexchange.com}
\email[Doe, John]{john.doe@stackexchange.com}
\email[Doe, Jane]{jane.doe@stackexchange.com}
\end{emailsFrom}

\end{document}

enter image description here

share|improve this answer
    
Pretty impressing output. What I do not like is that you already mix in format commands, that I would pass into the functions in order stay flexible. –  JJD Sep 1 '12 at 16:49
    
Just change \textbf{From:} into \toString and similarly for "To", if you prefer. –  egreg Sep 1 '12 at 17:44
    
No offense! But there is also the quotation hidden somewhere and there are many repetitions of conditional clauses that I would extract into a function e.g., \if@emailenv\else\set@email@separator{ ... }\fi\@email} I find them to be redundant. –  JJD Sep 1 '12 at 21:17
    
While I prepared my documentation I reviewed the commands and decided to use macro. The grouping into environments helps to keep some level of readability and has a logical structure. Only, I find your macro a little overwhelming. @Tom Bombadil: No offense. I appreciate your work!!! –  JJD Sep 7 '12 at 9:12
    
FYI: I opened another question to protect the email header against pagebreaks. –  JJD Sep 7 '12 at 9:39
add comment

This solution uses foreach from TikZ / PGF. You specify the names and mails as a list of the form name/mail,name/mail and so on:

The Code

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usepackage{xifthen}

\newcommand{\toString}{\textbf{To:} }

\newcommand{\emailto}[1]% list ; "/" separates mail and name, "," separates people
{   \xdef\maillist{}% empty maillist
    \foreach \x/\y [count=\c] in {#1}% for each iteration over the name/mail list, increase \c by one
    {   \ifthenelse{\c=1}% if first iteration... 
            {\xdef\addcomma{}}% leave out comma
            {\xdef\addcomma{,}}% else put one
        \ifthenelse{\equal{\x}{}}% if no name given
            {\xdef\maillist{\maillist\addcomma$<$\y$>$}}% put just <mail>
            {\xdef\maillist{\maillist\addcomma"\x"$<$\y$>$}}% else put "name"<mail>
    }
    \toString\maillist% output of the final list
}

\begin{document}

\emailto{John Doe/John.Doe@a.bc,Jane Dane/Jane.Dane@way.ne,/Denny.Crane@law.com}

\end{document}

The Result

enter image description here


Edit 1: A little generalization: Now you can reuse \email for other definitions. I have no idea how to do this with with optional parameters, as their number is not equal to the parameters.

The Code

\newcommand{\email}[1]% list ; "/" separates mail and name, "," separates people
{   \xdef\maillist{}% empty maillist
    \foreach \x/\y [count=\c] in {#1}% for each iteration over the name/mail list, increase \c by one
    {   \ifthenelse{\c=1}% if first iteration... 
            {\xdef\addcomma{}}% leave out comma
            {\xdef\addcomma{,}}% else put one
        \ifthenelse{\equal{\x}{}}% if no name given
            {\xdef\maillist{\maillist\addcomma$<$\y$>$}}% put just <mail>
            {\xdef\maillist{\maillist\addcomma"\x"$<$\y$>$}}% else put "name"<mail>
    }
}

\newcommand{\emailto}[1]
{   \email{#1}
    \textbf{To: }\maillist
}

\newcommand{\emailfrom}[1]
{   \email{#1}
    \textbf{From: }\maillist
}

The Result

\emailto{John Doe/John.Doe@a.bc,Jane Dane/Jane.Dane@way.ne,/Denny.Crane@law.com}

\emailfrom{John Doe/John.Doe@a.bc,Jane Dane/Jane.Dane@way.ne,/Denny.Crane@law.com}

enter image description here


Edit 2: And Now for Something Completely Different:
This solution uses xstring, the list format is (name)email;.
Please note that you also have to terminate the list with a semicolon ;

The Code

\documentclass[parskip]{scrartcl}
\usepackage[margin=10mm]{geometry}
\usepackage{xifthen}
\usepackage{xstring}
\usepackage{xcolor}

\newcommand{\email}[1]% (<name>)<email>;(<name>)<email>
{   \xdef\mylist{#1} % set mylist to the input
    \xdef\myentry{} % empty myentry
    \xdef\myname{} % empty myname
    \xdef\myemail{} % empty myemail
    \xdef\myoutput{} % empty myoutput
    \xdef\mynumber{} % empty mynumber
    \StrBefore{\mylist}{;}[\myentry]  % get everything in mylist before ; and save it to myentry, so this should be the first person, e.g (name)mail
    \StrLen{\myentry}[\mynumber] % save length of myentry to mynumber
    \whiledo{\mynumber>0} % while myentry is not empty (e.g. length > 0)
    {   \StrBetween{\myentry}{(}{)}[\myname] % extract what is between ( and ) in myentry and save it to myname
        \StrPosition{\myentry}{)}[\mynumber] % save position of ) to mynumber
        \ifthenelse{\mynumber>0} % if the character ) is found in myentry
            {   \StrBehind{\myentry}{)}[\myemail]} % then get everything behind ), e.g the email
            { \xdef\myemail{\myentry}}% otherwise (e.g. no name present) set myemail to myentry
        \StrLen{\myname}[\mynumber] % set mynumber to the length of mynem
        \ifthenelse{\mynumber>0} % if length of myname is non-zero (e.g one was provided)
            {   \xdef\myoutput{\myoutput"\myname"$<$\myemail$>$}} % then print "name"<mail>
            { \xdef\myoutput{\myoutput$<$\myemail$>$}}  % else print <mail>
        \StrBehind{\mylist}{;}[\mylist] % delete everything up to the first ; e.g the entry that was just worked with
        \StrBefore{\mylist}{;}[\myentry] % new myentry is everything before the next ;
        \StrLen{\myentry}[\mynumber] % determine length of myentry and save that number to mynumber
        \ifthenelse{\mynumber>0} % if a new myentry is present (e.g not end of list)
            {   \xdef\myoutput{\myoutput,}} % then add a comma
            {} % else do nothing
        }
    %\myoutput  % after all entrys were processed, output the result
}

\newcommand{\eMailTo}[1]%
{   \email{#1}
    \textbf{To: }\myoutput
}

\newcommand{\eMailFromColor}[2][green!50!gray]%
{   \email{#2}
    \textcolor{#1}{\textbf{From: }\myoutput}
}

\begin{document}

\eMailTo{(Doe, John)John.Doe@a.bc;(Dane, J. A. N. E)Jane.Dane@way.ne;Denny.Crane@law.com;}

\eMailFromColor{(Doe, John)John.Doe@a.bc;(Dane, J. A. N. E)Jane.Dane@way.ne;Denny.Crane@law.com;}

\eMailFromColor[red!80!black]{(Doe, John)John.Doe@a.bc;(Dane, J. A. N. E)Jane.Dane@way.ne;Denny.Crane@law.com;}

\end{document}

The Result

enter image description here

share|improve this answer
    
Pretty nice! Though, I have two requests. (1) I created the \email macro so that I can re-use it for \emailTo, \emailCc and \emailFrom and avoid duplicate code by this. How would integrate this? (2) I do not like the leading / in the example w/o the alias too much. Is there any alternative with optional parameters? –  JJD Sep 1 '12 at 14:38
    
Cool. I just figured out an alternative my own: \newcommand{\emailTo}[1]{\email{\toString}{#1}} and \newcommand{\emailFrom}[1]{\email{\fromString}{#1}}. You need to increase the number of arguments for the \email function. Thx! –  JJD Sep 1 '12 at 15:05
    
There is a problem when the alias is written in order last name, first name e.g., Doe, John. The commata is recognized as a separator between emails, but this a common writing scheme! –  JJD Sep 1 '12 at 15:15
1  
Slightly less ugly, but still not nice: surround the whole name with curly braces, like {Doe, John} –  Tom Bombadil Sep 1 '12 at 17:41
add comment

Your Answer

 
discard

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.