如何扩展电子邮件地址的宏以支持多个参数?

如何扩展电子邮件地址的宏以支持多个参数?

我准备了以下宏来格式化电子邮件标题中的电子邮件地址。

\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
}

宏的使用方法如下例所示。请注意[]用于可选参数,而不是 用于可选参数{}

\email[Doe, John]{[email protected]}
\emailFrom[Doe, John]{[email protected]}
\emailFrom{[email protected]}
\emailTo[Doe, John]{[email protected]}
\emailTo{[email protected]}

格式化的输出如下所示:

“Doe,约翰”<[电子邮件保护]>
从:“Doe,约翰”<[电子邮件保护]>
从:<[电子邮件保护]>
到:“Doe,约翰”<[电子邮件保护]>
到:<[电子邮件保护]>

我该如何扩展宏以便可以将其用于多个电子邮件地址?以下示例应该可以解释这个问题。正如您在第三个示例中看到的,别名的出现对于每个电子邮件条目都是单独的。

到:“Doe,约翰”<[电子邮件保护]>,“Doe,Jane”<[电子邮件保护]>
到:<[电子邮件保护]>、<[电子邮件保护]>
到:<[电子邮件保护]>,“Doe,Jane”<[电子邮件保护]>

由于我是第一次使用 Latex 中的宏,因此也欢迎您普遍改进我的命令或留下评论来改进。


更新:

在处理几封电子邮件时,我意识到这种情况也可能发生,电子邮件地址给定, 只有电子邮件别名。当有人转发电子邮件(例如,作为公司内部对话)时,就会发生这种情况。尽管如此,我还是接受这种格式作为有效的电子邮件标头。您是否认为有机会将此模式包含在宏中?这是一个例子。

From: John Doe
Subject: Re: E-Mail headers
Date: Wed, 22 Aug 2012 23:42:00 +0200
To: Jane Doe

答案1

对于一个地址和多个地址的情况,我会使用不同的语法:

\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{[email protected]}

\email[Doe, John]{[email protected]}

\emailTo{[email protected]}

\emailTo[Doe, John]{[email protected]}

\emailFrom{[email protected]}

\emailFrom[Doe, John]{[email protected]}



\begin{emails}
\email{[email protected]}
\email[Doe, John]{[email protected]}
\email[Doe, Jane]{[email protected]}
\end{emails}

\begin{emailsTo}
\email{[email protected]}
\email[Doe, John]{[email protected]}
\email[Doe, Jane]{[email protected]}
\end{emailsTo}

\begin{emailsFrom}
\email{[email protected]}
\email[Doe, John]{[email protected]}
\email[Doe, Jane]{[email protected]}
\end{emailsFrom}

\end{document}

在此处输入图片描述

答案2

该解决方案使用foreach来自TikZ/PGF 简介。您可以将姓名和邮件指定为name/mail,name/mail以下形式的列表:

代码

\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/[email protected],Jane Dane/[email protected],/[email protected]}

\end{document}

结果

在此处输入图片描述


编辑1:简单概括一下:现在您可以重用\email它进行其他定义。我不知道如何使用可选参数来实现这一点,因为它们的数量不等于参数。

代码

\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
}

结果

\emailto{John Doe/[email protected],Jane Dane/[email protected],/[email protected]}

\emailfrom{John Doe/[email protected],Jane Dane/[email protected],/[email protected]}

在此处输入图片描述


编辑2: 现在来谈谈完全不同的事情:
本解决方案使用xstring,列表格式为(name)email;
请注意,您还必须用分号终止列表;

代码

\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)[email protected];(Dane, J. A. N. E)[email protected];[email protected];}

\eMailFromColor{(Doe, John)[email protected];(Dane, J. A. N. E)[email protected];[email protected];}

\eMailFromColor[red!80!black]{(Doe, John)[email protected];(Dane, J. A. N. E)[email protected];[email protected];}

\end{document}

结果

在此处输入图片描述

相关内容