| 144 | } |
| 145 | |
| 146 | static void handle_from(struct mailinfo *mi, const struct strbuf *from) |
| 147 | { |
| 148 | char *at; |
| 149 | size_t el; |
| 150 | struct strbuf f; |
| 151 | |
| 152 | strbuf_init(&f, from->len); |
| 153 | strbuf_addbuf(&f, from); |
| 154 | |
| 155 | unquote_quoted_pair(&f); |
| 156 | |
| 157 | at = strchr(f.buf, '@'); |
| 158 | if (!at) { |
| 159 | parse_bogus_from(mi, from); |
| 160 | goto out; |
| 161 | } |
| 162 | |
| 163 | /* |
| 164 | * If we already have one email, don't take any confusing lines |
| 165 | */ |
| 166 | if (mi->email.len && strchr(at + 1, '@')) |
| 167 | goto out; |
| 168 | |
| 169 | /* Pick up the string around '@', possibly delimited with <> |
| 170 | * pair; that is the email part. |
| 171 | */ |
| 172 | while (at > f.buf) { |
| 173 | char c = at[-1]; |
| 174 | if (isspace(c)) |
| 175 | break; |
| 176 | if (c == '<') { |
| 177 | at[-1] = ' '; |
| 178 | break; |
| 179 | } |
| 180 | at--; |
| 181 | } |
| 182 | el = strcspn(at, " \n\t\r\v\f>"); |
| 183 | strbuf_reset(&mi->email); |
| 184 | strbuf_add(&mi->email, at, el); |
| 185 | strbuf_remove(&f, at - f.buf, el + (at[el] ? 1 : 0)); |
| 186 | |
| 187 | /* The remainder is name. It could be |
| 188 | * |
| 189 | * - "John Doe <john.doe@xz>" (a), or |
| 190 | * - "john.doe@xz (John Doe)" (b), or |
| 191 | * - "John (zzz) Doe <john.doe@xz> (Comment)" (c) |
| 192 | * |
| 193 | * but we have removed the email part, so |
| 194 | * |
| 195 | * - remove extra spaces which could stay after email (case 'c'), and |
| 196 | * - trim from both ends, possibly removing the () pair at the end |
| 197 | * (cases 'a' and 'b'). |
| 198 | */ |
| 199 | cleanup_space(&f); |
| 200 | strbuf_trim(&f); |
| 201 | if (f.buf[0] == '(' && f.len && f.buf[f.len - 1] == ')') { |
| 202 | strbuf_remove(&f, 0, 1); |
| 203 | strbuf_setlen(&f, f.len - 1); |
no test coverage detected