# Typesetting email with internet-style quoting using LaTeX?

I'm wondering if there exists a package, that would take so-called Internet-Style Quoted plain text of an email, and format it accordingly for a PDF output. Internet-style quoting is discussed on the Wikipedia page Posting style; so let's say I take an example from there, and I have the following to be the content of email.eml file:

At 10.01am Wednesday, Danny wrote:
> At 9.40am Wednesday, Jim wrote:
>> I'm going to suspend the mail service for approx. thirty
>> minutes tonight, starting at 5pm, to install some updates
>> and important fixes.

> Whoa!  Hold on.  I have a job scheduled at 5:30 which mails out
> a report to key tech staff.  Could you push it back an hour?
>
> By the way, which systems will be updated? I had some network
> problems after last week's update.  Will I have to reboot?

No problems. 6pm it is then.

Basically, I will update our WWW server and firewall.
No, you won't have to reboot.


Then, I'd imagine one could prepare something like an email.tex, which I could use to obtain a formatted PDF:

\documentclass{article}
\usepackage{???}

\begin{document}

\begin{QUOTEDEMAIL}
\input{email.eml}
\end{QUOTEDEMAIL}

\end{document}


I would be hoping that I'd at least have the control of choosing the color (grayscale) for the different levels of quoted replies (lines prefixed with '>')... But, if I can also control, say, fonts - or rendering lines instead of the '>' (like what Thunderbird does), that would be awesome! :)

Well, does anything similar to this exist?

-
I can smell the sweet \tikzmark solution of @PeterGrill :-) – percusse Mar 27 '12 at 6:07
Hi @percusse - wish I knew what that sweet solution is :) Cheers! – sdaau Mar 27 '12 at 6:09
If the desired solution was to have vertical lines to delineate the separate nesting depth, than perhaps \tikzmark would be useful but that would require editing the email text. So if it was to be used just a few times that would work. But, if you want to simply incorporate an existing email from an external file and not have to edit it, then listings is probably the way to go. – Peter Grill Mar 27 '12 at 14:52
@sdaau: If you are curious about \tikzmark have a look at How to draw arrows between parts of an equation to show the Math Distributive Property (Multiplication)?, or Draw a line through one column of a matrix – Peter Grill Mar 27 '12 at 14:53
Thanks for the comments, @PeterGrill - I indeed wanted to include an external file without further editing, so I concur about listings. However, many thanks for the \tikzmark links - those certainly point to a way of how a graphical solution (with vertical lines) would work. Cheers! – sdaau Mar 28 '12 at 4:40

This is only a partial solution, but it would be the way to go - using listings:

\documentclass{article}
\usepackage{listings}% http://ctan.org/pkg/listings
\usepackage{xcolor}% http://ctan.org/pkg/xcolor
\begin{document}
Here is the message:

\lstset{
basicstyle=\ttfamily\small,
morecomment=[l][\color{red!50}]{>>\ },
morecomment=[l][\color{green!80}]{>\ },
}

\lstinputlisting{email.eml}
\end{document}


Formatting of the respective reply-levels is done via morecomments, actually specifying that line of "code" to be a "comment". listings fails to pick up the empty line in the above example, but correctly interprets if you don't mind level-specific formatting using just

\lstset{
basicstyle=\ttfamily\small,
morecomment=[l][\color{red!50}]{>},
}


say. Note that using > elsewhere in the email might cause problems.

-
Many thanks for the answer, @Werner - that looks pretty good, so accepting it for now... Cheers! – sdaau Mar 27 '12 at 8:08

I just found another way - using the delimiter option of lstlisting, to insert tikz nodes at the quote characters. The nuisance is that you have to decide and specify amount of nesting levels (and their colors) apriori; but the good thing is that you can hide the processed quote characters altogether - while the other such characters pass untouched (and so no escaping or interventions are required in the raw text source); and also you can draw lines with decorations if you want (oh yeah, and you have to tex twice, because of tikz overlays):

The code is not really straightforward, some overloading of listings.sty stuff is required - see comments in the code below:

\documentclass{article}

\usepackage{listings}%
\usepackage{xcolor}%
% \usepackage{unravel}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing}
% \usepackage{trace}

% \pagecolor{yellow!15}
\begin{document}

\newcounter{testa} % just to see how newcounter works with resetting:
% \unravel{
\newcounter{testb}[testa]
%  \@cons \cl@testa {{testb}} -> \xdef \cl@testa {\@elt {testb}}
% }

\makeatletter
\def\lnm{\the\lst@lineno}
\def\lnc{\the\lst@column}
\def\lnp{\the\lst@pos} % character column, but as -1, -34..
% \lst@lineno is newcount; "let" it to
% a macro named accordingly so can link to it in newcounter
\let\c@lst@lineno\lst@lineno
\let\cl@lst@lineno\relax
\newcounter{unm}[lst@lineno]
% \@cons\cl@lst@lineno{{unm}} % ! TeX capacity exceeded, sorry
% \xdef\cl@lst@lineno{\@elt{unm}} %cannot: unm needs to be added to list of lst@lineno, which is reset upon addtocounter, which lst@lineno doesn't use
% hack in lst@MProcessListing (listings.sty), to call \extralstlinecall before change of line number
\gdef\extralstlinecall{\typeout{EXTRA LINE \lnm}}
\def\lst@MProcessListing{%
\lst@XPrintToken \lst@EOLUpdate \lsthk@InitVarsBOL
\extralstlinecall
\ifnum \lst@lineno>\lst@lastline
\lst@ifdropinput \lst@LeaveMode \fi
\ifx\lst@linerange\@empty
\expandafter\expandafter\expandafter\lst@EndProcessListing
\else
\lst@interrange
\lst@GetLineInterval
\expandafter\expandafter\expandafter\lst@SkipToFirst
\fi
\else
\expandafter\lst@BOLGobble
\fi}
\makeatother

\tikzstyle{every picture}+=[remember picture] % must have
\tikzstyle{nn} = [inner sep=0pt, outer sep=0pt, minimum size=0pt]
\tikzstyle{qln} = [line width=2pt]
% quote colors:
\colorlet{qcol0}{blue!50}
\colorlet{qcol1}{orange!50}
\colorlet{qcol2}{cyan!50}
\gdef\lastqcol{2} % declare how many levels/colors we expect (last index)
\colorlet{defaultcol}{.} % current color
% percolumn node lists - same ammount as qcols
\gdef\setpcol#1#2{%
\global\expandafter\edef\csname pcoll-#1\endcsname{#2}%
}
\expandafter\ifx\csname pcoll-#1\endcsname\empty%
\global\expandafter\edef\csname pcoll-#1\endcsname{#2}%
\else%
\global\expandafter\edef\csname pcoll-#1\endcsname{\csname pcoll-#1\endcsname,#2}%
\fi%
}
\setpcol{0}{}
\setpcol{1}{}
\setpcol{2}{}
% we know nodes are NXX-YY here, so
\global\let\e\relax
\gdef\getnameXY N#1-#2\e#3#4{%
%\typeout{getname \string#1, \string#2, \string#3, \string#4}%
\xdef#3{#1}%
\xdef#4{#2}%
}
% \getnameXY NXX-YY\e\tmpa\tmpb
% \typeout{tmpa \tmpa, tmpb \tmpb}

% {\uccodeA=10
%     \uppercase{\xdef\lf{A}}}

\xdef\qnodelist{}
\xdef\qnodelistx{}
\xdef\qnodelisty{}
\xdef\lastlnm{0}
\def\repl{%
\tikzstyle{every picture}+=[remember picture] % must have
\pgfmathtruncatemacro{\clnp}{-1*\lnp}%
\ifnum\lnm=\lastlnm%
\stepcounter{unm}%
\else%
\setcounter{unm}{0}%
\fi%
\xdef\lastlnm{\lnm}%
\ifnum\clnp>\lastqcol%
\setcounter{unm}{\lastqcol}%
> % output verbatim character; cannot insert LF (\n): ^^J; also give space betw. char and % sign!
\else%
\edef\tnnd{N\lnm-\theunm}%
\tikz[baseline=(\tnnd.base)]{%
\node[nn] (\tnnd) {\phantom{>}};%
\draw[qln,draw=qcol\theunm] (current bounding box.north) -- (\tnnd.south);%
}%
\ifx\qnodelist\empty%
\xdef\qnodelist{\tnnd}%
\xdef\qnodelistx{\lnm}%
\xdef\qnodelisty{\clnp}%
\else%
\xdef\qnodelist{\qnodelist,\tnnd}%
\xdef\qnodelistx{\qnodelistx,\lnm}%
\xdef\qnodelisty{\qnodelisty,\clnp}%
\fi%
\color{qcol\theunm}% this spills color; to stop it, use a reset in \extralstlinecall!
\fi%
%\typeout{ln \lnm, col \lnc, pos \clnp, unm \theunm}%
}
\gdef\extralstlinecall{%
\color{defaultcol}%
\typeout{EXTRA LINE \lnm}%
}

\lstset{
basicstyle=\ttfamily\small,
% {\^^M}{{\^^M}}1 % matches, but cannot insert, end of line (actually, para!)
literate={>}{{\repl}}1 ,% kills the >,>> morecomments!
morecomment=[l][\color{red!50}]{>>\ },
morecomment=[l][\color{green!80}]{>\ },
%morecomment=[f][\color{green!80}][0]{\^^M}, % locks
}

\begin{lstlisting}
At 10.01am Wednesday, Danny wrote:
> At 9.40am Wednesday, Jim wrote: >>check here<<
>> I'm going to suspend the mail service for approx. thirty
>> minutes tonight, starting at 5pm, to install some updates
>> and important fixes.
>
> Whoa!  Hold on.  I have a job scheduled at 5:30 which mails out
> a report to key tech staff.  Could you push it back an hour?
>
>> I'm going to suspend the mail service for approx. thirty
>> minutes tonight, starting at 5pm, to install some updates
>> and important fixes.
>
> By the way, which systems will be updated? I had some network
> problems after last week's update.  Will I have to reboot?

No problems. 6pm it is then.

Basically, I will update our WWW server and firewall.
No, you won't have to reboot.

> By the way, which systems will be updated? I had some network
> problems after last week's update.  Will I have to reboot?
> Will I have to reboot?

No, you won't have to reboot.
\end{lstlisting}

\qnodelist

\tikzstyle{bnl} = [line width=1pt,decoration=snake,decorate]
% \begin{tikzpicture}[overlay]
\foreach \ix in {0,...,\lastqcol}{
\xdef\strt{}\xdef\endr{}
\expandafter\edef\expandafter\ptmp{\csname pcoll-\ix\endcsname}
\typeout{ptmp: '\ptmp'}
% will not loop if \ptmp empty; that's why all pcoll-\ix must be initialized to empty
\ifx\ptmp\empty\else
\foreach \inn in \ptmp {
\expandafter\getnameXY\inn\e\trow\tcol % get
\typeout{\inn, \trow, \tcol, '\strt', '\endr'}
\ifx\strt\empty
\xdef\strt{\trow}
\xdef\endr{\trow}
\else
\pgfmathtruncatemacro{\isNeighbor}{\trow-\endr == 1}
\typeout{isNeigh \isNeighbor: \trow, \strt, \endr}
\ifnum\isNeighbor=1{}\else
\tikz[overlay]\draw[bnl,qcol\tcol!60] (N\strt-\tcol) -- (N\endr-\tcol);
\xdef\strt{\trow}
\fi
\xdef\endr{\trow}
\fi
} % foreach
\tikz[overlay]\draw[bnl,qcol\tcol!60] (N\strt-\tcol) -- (N\endr-\tcol);
\fi
}
% \end{tikzpicture}

\end{document}
`
-