![如何扩展电子邮件地址的宏以支持多个参数?](https://linux22.com/image/254749/%E5%A6%82%E4%BD%95%E6%89%A9%E5%B1%95%E7%94%B5%E5%AD%90%E9%82%AE%E4%BB%B6%E5%9C%B0%E5%9D%80%E7%9A%84%E5%AE%8F%E4%BB%A5%E6%94%AF%E6%8C%81%E5%A4%9A%E4%B8%AA%E5%8F%82%E6%95%B0%EF%BC%9F.png)
我准备了以下宏来格式化电子邮件标题中的电子邮件地址。
\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}