1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
{{/*
  Rendering of one correspondent's name, shared by every HTML view.

  The distinction it draws is the same one the text renderings draw with ~ and
  quotes: a petname was assigned here and is vouched for, a display name came
  out of a From: header and is a claim by whoever sent the mail. This archive
  contains "Deutsche-Baпk AG" with a Cyrillic п, and "Ζaκaria" in Greek letters
  arriving through GitHub, both of which used to render exactly like a name the
  reader had chosen.

  It is one defined template rather than markup repeated in each view because
  the marking is a security property: four copies are four chances for one of
  them to quietly print a bare .Claimed, which is the state this replaced.

  "name" renders the name alone; "nameAddr" adds the address beneath it, for
  the places with room for two lines. "penLink" is the way to the settings
  page, where a name is assigned; it lives here beside the marking because the
  two are the same subject — what this contact is called, and by whom.
*/}}
{{define "name"}}
  {{- if .Petname -}}
    <span class="pet" title="A name you assigned to {{.Address}}. Local to mailweb and never sent.">{{.Petname}}</span>
  {{- else if .Claimed -}}
    <span class="claimed" title="Written by the sender and not verified by anything.">&ldquo;{{.Claimed}}&rdquo;</span>
    {{- if .Mixed}} <span class="mixed" title="This name mixes alphabets inside a single word — Latin with Cyrillic or Greek — which is how a lookalike name is built. It is not proof of anything, but it is worth a second look at the address.">mixed alphabets</span>{{end -}}
  {{- else -}}
    <span class="claimed">{{.Address}}</span>
  {{- end -}}
{{end}}

{{define "nameAddr"}}
  {{- template "name" . -}}
  {{- if or .Petname .Claimed}}<br><span class="addr-line">{{.Address}}</span>{{end -}}
{{end}}

{{/*
  A list of correspondents, each marked. Takes a []mailtext.Name.

  The address is appended only where a name was printed in front of it. With no
  petname and no claimed name "name" renders the address itself, and following
  that with the same address in angle brackets says it twice — which is what a
  recipient list mostly is, since a To: header usually carries bare addresses.
*/}}
{{define "nameList"}}
  {{- range $i, $n := . }}{{if $i}}, {{end}}{{template "name" $n}}
    {{- if or $n.Petname $n.Claimed}} &lt;{{$n.Address}}&gt;{{end}}{{end -}}
{{end}}

{{/*
  Who a message was between: one line saying either who wrote it or who it went
  to, and who else was copied.

  Takes a msgRow. It is one partial rather than markup in each view for the same
  reason "name" is: the index, the conversation page and a message's own page
  all answer this question, and three copies are three chances for one to print
  a recipient list the reader cannot tell from a name they chose themselves.
  That is not hypothetical — it is what the conversation page did, printing a
  preformatted "Name <addr>" string straight out of somebody else's header.

  Which side is shown is isOutgoing's answer, carried here as .Direction: for
  mail this account wrote, "From: you" is the one fact the reader already has,
  and who it went to is the thing worth the line.

  Cc is shown whenever there is one, in both directions. On incoming mail it is
  what distinguishes a letter written to you from one you were copied on, and
  20578 messages in this archive carry one. Bcc is shown if it is ever present;
  no received message carries one, and mailweb's own sender writes none, so in
  practice this renders nothing — it is here so that the day something does
  write one, it is not silently dropped.
*/}}
{{define "correspondents"}}
  {{- if eq .Direction "sent" -}}
    <span class="dir dir-sent">→</span>To:
    {{- if .To}} {{template "nameList" .To}}{{else}} —{{end}}
  {{- else -}}
    <span class="dir dir-recv">←</span>From: {{template "name" .From}} &lt;{{.From.Address}}&gt;
  {{- end}}
  {{- with .Cc}}<br><span class="cc-line">Cc: {{template "nameList" .}}</span>{{end}}
  {{- with .Bcc}}<br><span class="cc-line">Bcc: {{template "nameList" .}}</span>{{end}}
  {{- /* Nobody visible was addressed, yet it arrived: the reader was blind
         copied, and Delivered-To is the only header naming them. Saying so is
         the difference between that and a letter written to them directly,
         which is otherwise exactly what it looks like. */ -}}
  {{- with .DeliveredTo}}<br><span class="cc-line" title="No recipient header on this message names you; it reached this account as a blind copy. This address comes from the Delivered-To header added on delivery.">To: undisclosed recipients — delivered to {{.}}</span>{{end}}
{{end}}

{{/*
  The way to name a contact. Takes a contactPen: the path-escaped address and
  the URL to come back to.

  It replaced an inline petname field in the listing and another in the contact
  header. Two forms meant two places that had to agree about what naming is,
  and neither had room to say anything about it — a bare text input beside a
  stranger's address, with no mention that the name is local, never sent, and
  not a way to identify anybody. That is now on one page which has room for it.

  The cost is honest: naming a stranger while scanning the listing is a page
  away rather than in the row. Hence Return, so the way back is one click and
  lands where the reader was, ?show=hidden and all.
*/}}
{{define "penLink"}}
  <a class="pen-link" href="/contact/{{.AddrEscaped}}/settings?return={{.Return}}"
     title="Name this contact, and everything else about it">✎</a>
{{end}}

{{define "nameStyle"}}
  .pet     { font-weight: 600; }
  .claimed { font-weight: normal; color: var(--text-meta); font-style: italic; }
  .addr-line { color: var(--text-meta); font-size: 0.85em; }
  {{/* The direction arrow and the copied-to lines belong to the
       "correspondents" partial above, so they live here rather than in each
       page that mounts it — a view that has the markup and not the style
       renders an unstyled arrow. */}}
  .dir     { font-size: 0.8rem; font-weight: bold; margin-right: 0.4rem; }
  .dir-recv { color: var(--text-meta); }
  .dir-sent { color: var(--link); }
  .cc-line { color: var(--text-meta); }
  .mixed {
    font-size: 0.75em; color: var(--danger, #c0392b);
    border: 1px solid currentColor; border-radius: 3px;
    padding: 0 0.25em; white-space: nowrap; font-style: normal;
  }
  a.pen-link {
    color: var(--text-meta); text-decoration: none; font-size: 0.9em;
    padding: 0 0.25em; border-radius: 3px; vertical-align: middle;
  }
  a.pen-link:hover { color: var(--text); background: var(--border); }
{{end}}