Hex Artifact Content
Logged in as anonymous

Artifact bbe46eca75aa0f7687381067513e9b9c53a5d59d54595682704ada4d3c06c88c:


0000: 75 73 65 20 63 72 61 74 65 3a 3a 7b 0a 09 43 75  use crate::{..Cu
0010: 72 73 6f 72 2c 0a 09 74 65 6c 65 67 72 61 6d 3a  rsor,..telegram:
0020: 3a 54 65 6c 65 67 72 61 6d 54 72 61 6e 73 70 6f  :TelegramTranspo
0030: 72 74 2c 0a 09 75 74 69 6c 73 3a 3a 7b 0a 09 09  rt,..utils::{...
0040: 41 74 74 61 63 68 6d 65 6e 74 2c 0a 09 09 52 45  Attachment,...RE
0050: 5f 44 4f 4d 41 49 4e 2c 0a 09 09 76 61 6c 69 64  _DOMAIN,...valid
0060: 61 74 65 2c 0a 09 7d 2c 0a 7d 3b 0a 0a 75 73 65  ate,..},.};..use
0070: 20 73 74 64 3a 3a 7b 0a 09 62 6f 72 72 6f 77 3a   std::{..borrow:
0080: 3a 43 6f 77 2c 0a 09 63 6f 6c 6c 65 63 74 69 6f  :Cow,..collectio
0090: 6e 73 3a 3a 7b 0a 09 09 48 61 73 68 4d 61 70 2c  ns::{...HashMap,
00a0: 0a 09 09 48 61 73 68 53 65 74 2c 0a 09 7d 2c 0a  ...HashSet,..},.
00b0: 09 69 6f 3a 3a 45 72 72 6f 72 2c 0a 09 73 79 6e  .io::Error,..syn
00c0: 63 3a 3a 41 72 63 2c 0a 7d 3b 0a 0a 75 73 65 20  c::Arc,.};..use 
00d0: 61 73 79 6e 63 5f 63 6f 6d 70 61 74 3a 3a 43 6f  async_compat::Co
00e0: 6d 70 61 74 3b 0a 75 73 65 20 6d 61 69 6c 69 6e  mpat;.use mailin
00f0: 5f 65 6d 62 65 64 64 65 64 3a 3a 7b 0a 09 52 65  _embedded::{..Re
0100: 73 70 6f 6e 73 65 2c 0a 09 72 65 73 70 6f 6e 73  sponse,..respons
0110: 65 3a 3a 7b 0a 09 09 49 4e 54 45 52 4e 41 4c 5f  e::{...INTERNAL_
0120: 45 52 52 4f 52 2c 0a 09 09 49 4e 56 41 4c 49 44  ERROR,...INVALID
0130: 5f 43 52 45 44 45 4e 54 49 41 4c 53 2c 0a 09 09  _CREDENTIALS,...
0140: 4e 4f 5f 4d 41 49 4c 42 4f 58 2c 0a 09 09 4f 4b  NO_MAILBOX,...OK
0150: 0a 09 7d 2c 0a 7d 3b 0a 75 73 65 20 72 65 67 65  ..},.};.use rege
0160: 78 3a 3a 7b 0a 09 52 65 67 65 78 2c 0a 09 65 73  x::{..Regex,..es
0170: 63 61 70 65 2c 0a 7d 3b 0a 75 73 65 20 73 74 61  cape,.};.use sta
0180: 63 6b 65 64 5f 65 72 72 6f 72 73 3a 3a 7b 0a 09  cked_errors::{..
0190: 52 65 73 75 6c 74 2c 0a 09 53 74 61 63 6b 61 62  Result,..Stackab
01a0: 6c 65 45 72 72 2c 0a 09 62 61 69 6c 2c 0a 7d 3b  leErr,..bail,.};
01b0: 0a 75 73 65 20 74 67 62 6f 74 3a 3a 74 79 70 65  .use tgbot::type
01c0: 73 3a 3a 43 68 61 74 50 65 65 72 49 64 3b 0a 0a  s::ChatPeerId;..
01d0: 2f 2f 2f 20 60 53 6f 6d 65 48 65 61 64 65 72 73  /// `SomeHeaders
01e0: 60 20 6f 62 6a 65 63 74 20 74 6f 20 73 74 6f 72  ` object to stor
01f0: 65 20 64 61 74 61 20 74 68 72 6f 75 67 68 20 53  e data through S
0200: 4d 54 50 20 73 65 73 73 69 6f 6e 0a 23 5b 64 65  MTP session.#[de
0210: 72 69 76 65 28 43 6c 6f 6e 65 2c 20 44 65 62 75  rive(Clone, Debu
0220: 67 29 5d 0a 73 74 72 75 63 74 20 53 6f 6d 65 48  g)].struct SomeH
0230: 65 61 64 65 72 73 20 7b 0a 09 66 72 6f 6d 3a 20  eaders {..from: 
0240: 53 74 72 69 6e 67 2c 0a 09 74 6f 3a 20 56 65 63  String,..to: Vec
0250: 3c 53 74 72 69 6e 67 3e 2c 0a 7d 0a 0a 2f 2f 2f  <String>,.}..///
0260: 20 60 4d 61 69 6c 53 65 72 76 65 72 60 20 43 65   `MailServer` Ce
0270: 6e 74 72 61 6c 20 6f 62 6a 65 63 74 20 77 69 74  ntral object wit
0280: 68 20 54 47 20 61 70 69 20 61 6e 64 20 63 6f 6e  h TG api and con
0290: 66 69 67 75 72 61 74 69 6f 6e 0a 23 5b 64 65 72  figuration.#[der
02a0: 69 76 65 28 43 6c 6f 6e 65 2c 20 44 65 62 75 67  ive(Clone, Debug
02b0: 29 5d 0a 70 75 62 20 73 74 72 75 63 74 20 4d 61  )].pub struct Ma
02c0: 69 6c 53 65 72 76 65 72 20 7b 0a 09 64 61 74 61  ilServer {..data
02d0: 3a 20 56 65 63 3c 75 38 3e 2c 0a 09 68 65 61 64  : Vec<u8>,..head
02e0: 65 72 73 3a 20 4f 70 74 69 6f 6e 3c 53 6f 6d 65  ers: Option<Some
02f0: 48 65 61 64 65 72 73 3e 2c 0a 09 72 65 6c 61 79  Headers>,..relay
0300: 3a 20 62 6f 6f 6c 2c 0a 09 74 67 3a 20 41 72 63  : bool,..tg: Arc
0310: 3c 54 65 6c 65 67 72 61 6d 54 72 61 6e 73 70 6f  <TelegramTranspo
0320: 72 74 3e 2c 0a 09 66 69 65 6c 64 73 3a 20 48 61  rt>,..fields: Ha
0330: 73 68 53 65 74 3c 53 74 72 69 6e 67 3e 2c 0a 09  shSet<String>,..
0340: 61 64 64 72 65 73 73 3a 20 52 65 67 65 78 2c 0a  address: Regex,.
0350: 7d 0a 0a 69 6d 70 6c 20 4d 61 69 6c 53 65 72 76  }..impl MailServ
0360: 65 72 20 7b 0a 09 2f 2f 2f 20 49 6e 69 74 69 61  er {../// Initia
0370: 6c 69 7a 65 20 41 50 49 20 61 6e 64 20 72 65 61  lize API and rea
0380: 64 20 63 6f 6e 66 69 67 75 72 61 74 69 6f 6e 0a  d configuration.
0390: 09 70 75 62 20 66 6e 20 6e 65 77 28 73 65 74 74  .pub fn new(sett
03a0: 69 6e 67 73 3a 20 63 6f 6e 66 69 67 3a 3a 43 6f  ings: config::Co
03b0: 6e 66 69 67 29 20 2d 3e 20 52 65 73 75 6c 74 3c  nfig) -> Result<
03c0: 4d 61 69 6c 53 65 72 76 65 72 3e 20 7b 0a 09 09  MailServer> {...
03d0: 6c 65 74 20 61 70 69 5f 6b 65 79 20 3d 20 73 65  let api_key = se
03e0: 74 74 69 6e 67 73 2e 67 65 74 5f 73 74 72 69 6e  ttings.get_strin
03f0: 67 28 22 61 70 69 5f 6b 65 79 22 29 0a 09 09 09  g("api_key")....
0400: 2e 63 6f 6e 74 65 78 74 28 22 5b 73 6d 74 70 32  .context("[smtp2
0410: 74 67 2e 74 6f 6d 6c 5d 20 6d 69 73 73 69 6e 67  tg.toml] missing
0420: 20 5c 22 61 70 69 5f 6b 65 79 5c 22 20 70 61 72   \"api_key\" par
0430: 61 6d 65 74 65 72 2e 5c 6e 22 29 3f 3b 0a 09 09  ameter.\n")?;...
0440: 6c 65 74 20 6d 75 74 20 72 65 63 69 70 69 65 6e  let mut recipien
0450: 74 73 20 3d 20 48 61 73 68 4d 61 70 3a 3a 6e 65  ts = HashMap::ne
0460: 77 28 29 3b 0a 09 09 66 6f 72 20 28 6e 61 6d 65  w();...for (name
0470: 2c 20 76 61 6c 75 65 29 20 69 6e 20 73 65 74 74  , value) in sett
0480: 69 6e 67 73 2e 67 65 74 5f 74 61 62 6c 65 28 22  ings.get_table("
0490: 72 65 63 69 70 69 65 6e 74 73 22 29 0a 09 09 09  recipients")....
04a0: 2e 65 78 70 65 63 74 28 22 5b 73 6d 74 70 32 74  .expect("[smtp2t
04b0: 67 2e 74 6f 6d 6c 5d 20 6d 69 73 73 69 6e 67 20  g.toml] missing 
04c0: 74 61 62 6c 65 20 5c 22 72 65 63 69 70 69 65 6e  table \"recipien
04d0: 74 73 5c 22 2e 5c 6e 22 29 0a 09 09 7b 0a 09 09  ts\".\n")...{...
04e0: 09 6c 65 74 20 76 61 6c 75 65 20 3d 20 76 61 6c  .let value = val
04f0: 75 65 2e 69 6e 74 6f 5f 69 6e 74 28 29 0a 09 09  ue.into_int()...
0500: 09 09 2e 63 6f 6e 74 65 78 74 28 22 5b 73 6d 74  ...context("[smt
0510: 70 32 74 67 2e 74 6f 6d 6c 5d 20 5c 22 72 65 63  p2tg.toml] \"rec
0520: 69 70 69 65 6e 74 5c 22 20 74 61 62 6c 65 20 76  ipient\" table v
0530: 61 6c 75 65 73 20 73 68 6f 75 6c 64 20 62 65 20  alues should be 
0540: 69 6e 74 65 67 65 72 73 2e 5c 6e 22 29 3f 3b 0a  integers.\n")?;.
0550: 09 09 09 72 65 63 69 70 69 65 6e 74 73 2e 69 6e  ...recipients.in
0560: 73 65 72 74 28 6e 61 6d 65 2c 20 76 61 6c 75 65  sert(name, value
0570: 29 3b 0a 09 09 7d 0a 0a 09 09 6c 65 74 20 74 67  );...}....let tg
0580: 20 3d 20 41 72 63 3a 3a 6e 65 77 28 54 65 6c 65   = Arc::new(Tele
0590: 67 72 61 6d 54 72 61 6e 73 70 6f 72 74 3a 3a 6e  gramTransport::n
05a0: 65 77 28 61 70 69 5f 6b 65 79 2c 20 72 65 63 69  ew(api_key, reci
05b0: 70 69 65 6e 74 73 2c 20 26 73 65 74 74 69 6e 67  pients, &setting
05c0: 73 29 3f 29 3b 0a 09 09 6c 65 74 20 66 69 65 6c  s)?);...let fiel
05d0: 64 73 20 3d 20 48 61 73 68 53 65 74 3a 3a 3c 53  ds = HashSet::<S
05e0: 74 72 69 6e 67 3e 3a 3a 66 72 6f 6d 5f 69 74 65  tring>::from_ite
05f0: 72 28 73 65 74 74 69 6e 67 73 2e 67 65 74 5f 61  r(settings.get_a
0600: 72 72 61 79 28 22 66 69 65 6c 64 73 22 29 0a 09  rray("fields")..
0610: 09 09 2e 65 78 70 65 63 74 28 22 5b 73 6d 74 70  ...expect("[smtp
0620: 32 74 67 2e 74 6f 6d 6c 5d 20 5c 22 66 69 65 6c  2tg.toml] \"fiel
0630: 64 73 5c 22 20 73 68 6f 75 6c 64 20 62 65 20 61  ds\" should be a
0640: 6e 20 61 72 72 61 79 22 29 0a 09 09 09 2e 69 74  n array").....it
0650: 65 72 28 29 2e 6d 61 70 28 7c 78 7c 20 78 2e 63  er().map(|x| x.c
0660: 6c 6f 6e 65 28 29 2e 69 6e 74 6f 5f 73 74 72 69  lone().into_stri
0670: 6e 67 28 29 2e 65 78 70 65 63 74 28 22 73 68 6f  ng().expect("sho
0680: 75 6c 64 20 62 65 20 73 74 72 69 6e 67 73 22 29  uld be strings")
0690: 29 29 3b 0a 09 09 6c 65 74 20 6d 75 74 20 64 6f  ));...let mut do
06a0: 6d 61 69 6e 73 3a 20 48 61 73 68 53 65 74 3c 53  mains: HashSet<S
06b0: 74 72 69 6e 67 3e 20 3d 20 48 61 73 68 53 65 74  tring> = HashSet
06c0: 3a 3a 6e 65 77 28 29 3b 0a 09 09 6c 65 74 20 65  ::new();...let e
06d0: 78 74 72 61 5f 64 6f 6d 61 69 6e 73 20 3d 20 73  xtra_domains = s
06e0: 65 74 74 69 6e 67 73 2e 67 65 74 5f 61 72 72 61  ettings.get_arra
06f0: 79 28 22 64 6f 6d 61 69 6e 73 22 29 2e 73 74 61  y("domains").sta
0700: 63 6b 28 29 3f 3b 0a 09 09 66 6f 72 20 64 6f 6d  ck()?;...for dom
0710: 61 69 6e 20 69 6e 20 65 78 74 72 61 5f 64 6f 6d  ain in extra_dom
0720: 61 69 6e 73 20 7b 0a 09 09 09 6c 65 74 20 64 6f  ains {....let do
0730: 6d 61 69 6e 20 3d 20 64 6f 6d 61 69 6e 2e 74 6f  main = domain.to
0740: 5f 73 74 72 69 6e 67 28 29 2e 74 6f 5f 6c 6f 77  _string().to_low
0750: 65 72 63 61 73 65 28 29 3b 0a 09 09 09 69 66 20  ercase();....if 
0760: 52 45 5f 44 4f 4d 41 49 4e 2e 69 73 5f 6d 61 74  RE_DOMAIN.is_mat
0770: 63 68 28 26 64 6f 6d 61 69 6e 29 20 7b 0a 09 09  ch(&domain) {...
0780: 09 09 64 6f 6d 61 69 6e 73 2e 69 6e 73 65 72 74  ..domains.insert
0790: 28 64 6f 6d 61 69 6e 29 3b 0a 09 09 09 7d 20 65  (domain);....} e
07a0: 6c 73 65 20 7b 0a 09 09 09 09 70 61 6e 69 63 21  lse {.....panic!
07b0: 28 22 5b 73 6d 74 70 32 74 67 2e 74 6f 6d 6c 5d  ("[smtp2tg.toml]
07c0: 20 63 61 6e 27 74 20 63 68 65 63 6b 20 6f 66 20   can't check of 
07d0: 64 6f 6d 61 69 6e 73 20 69 6e 20 5c 22 64 6f 6d  domains in \"dom
07e0: 61 69 6e 73 5c 22 3a 20 7b 64 6f 6d 61 69 6e 7d  ains\": {domain}
07f0: 22 29 3b 0a 09 09 09 7d 0a 09 09 7d 0a 09 09 6c  ");....}...}...l
0800: 65 74 20 64 6f 6d 61 69 6e 73 20 3d 20 64 6f 6d  et domains = dom
0810: 61 69 6e 73 2e 69 6e 74 6f 5f 69 74 65 72 28 29  ains.into_iter()
0820: 2e 6d 61 70 28 7c 73 7c 20 65 73 63 61 70 65 28  .map(|s| escape(
0830: 26 73 29 29 0a 09 09 09 2e 63 6f 6c 6c 65 63 74  &s)).....collect
0840: 3a 3a 3c 56 65 63 3c 53 74 72 69 6e 67 3e 3e 28  ::<Vec<String>>(
0850: 29 2e 6a 6f 69 6e 28 22 7c 22 29 3b 0a 09 09 6c  ).join("|");...l
0860: 65 74 20 61 64 64 72 65 73 73 20 3d 20 52 65 67  et address = Reg
0870: 65 78 3a 3a 6e 65 77 28 26 66 6f 72 6d 61 74 21  ex::new(&format!
0880: 28 22 5e 28 3f 50 3c 75 73 65 72 3e 5b 61 2d 7a  ("^(?P<user>[a-z
0890: 30 2d 39 5d 5b 2d 61 2d 7a 30 2d 39 5d 29 28 40  0-9][-a-z0-9])(@
08a0: 28 7b 64 6f 6d 61 69 6e 73 7d 29 29 24 22 29 29  ({domains}))$"))
08b0: 2e 73 74 61 63 6b 28 29 3f 3b 0a 09 09 6c 65 74  .stack()?;...let
08c0: 20 72 65 6c 61 79 20 3d 20 6d 61 74 63 68 20 73   relay = match s
08d0: 65 74 74 69 6e 67 73 2e 67 65 74 5f 73 74 72 69  ettings.get_stri
08e0: 6e 67 28 22 75 6e 6b 6e 6f 77 6e 22 29 0a 09 09  ng("unknown")...
08f0: 09 2e 63 6f 6e 74 65 78 74 28 22 5b 73 6d 74 70  ..context("[smtp
0900: 32 74 67 2e 74 6f 6d 6c 5d 20 63 61 6e 27 74 20  2tg.toml] can't 
0910: 67 65 74 20 5c 22 75 6e 6b 6e 6f 77 6e 5c 22 20  get \"unknown\" 
0920: 70 6f 6c 69 63 79 2e 5c 6e 22 29 3f 2e 61 73 5f  policy.\n")?.as_
0930: 73 74 72 28 29 0a 09 09 7b 0a 09 09 09 22 72 65  str()...{...."re
0940: 6c 61 79 22 20 3d 3e 20 74 72 75 65 2c 0a 09 09  lay" => true,...
0950: 09 22 64 65 6e 79 22 20 3d 3e 20 66 61 6c 73 65  ."deny" => false
0960: 2c 0a 09 09 09 5f 20 3d 3e 20 7b 0a 09 09 09 09  ,...._ => {.....
0970: 62 61 69 6c 21 28 22 5b 73 6d 74 70 32 74 67 2e  bail!("[smtp2tg.
0980: 74 6f 6d 6c 5d 20 5c 22 75 6e 6b 6e 6f 77 6e 5c  toml] \"unknown\
0990: 22 20 73 68 6f 75 6c 64 20 62 65 20 65 69 74 68  " should be eith
09a0: 65 72 20 5c 22 72 65 6c 61 79 5c 22 20 6f 72 20  er \"relay\" or 
09b0: 5c 22 64 65 6e 79 5c 22 2e 5c 6e 22 29 3b 0a 09  \"deny\".\n");..
09c0: 09 09 7d 2c 0a 09 09 7d 3b 0a 0a 09 09 4f 6b 28  ..},...};....Ok(
09d0: 4d 61 69 6c 53 65 72 76 65 72 20 7b 0a 09 09 09  MailServer {....
09e0: 64 61 74 61 3a 20 76 65 63 21 28 29 2c 0a 09 09  data: vec!(),...
09f0: 09 68 65 61 64 65 72 73 3a 20 4e 6f 6e 65 2c 0a  .headers: None,.
0a00: 09 09 09 72 65 6c 61 79 2c 0a 09 09 09 74 67 2c  ...relay,....tg,
0a10: 0a 09 09 09 66 69 65 6c 64 73 2c 0a 09 09 09 61  ....fields,....a
0a20: 64 64 72 65 73 73 2c 0a 09 09 7d 29 0a 09 7d 0a  ddress,...})..}.
0a30: 0a 09 2f 2f 2f 20 52 65 74 75 72 6e 73 20 69 64  ../// Returns id
0a40: 20 66 6f 72 20 70 72 6f 76 69 64 65 64 20 65 6d   for provided em
0a50: 61 69 6c 20 61 64 64 72 65 73 73 0a 09 66 6e 20  ail address..fn 
0a60: 67 65 74 5f 69 64 20 28 26 73 65 6c 66 2c 20 6e  get_id (&self, n
0a70: 61 6d 65 3a 20 26 73 74 72 29 20 2d 3e 20 52 65  ame: &str) -> Re
0a80: 73 75 6c 74 3c 26 43 68 61 74 50 65 65 72 49 64  sult<&ChatPeerId
0a90: 3e 20 7b 0a 09 09 2f 2f 20 68 65 72 65 20 77 65  > {...// here we
0aa0: 20 6e 65 65 64 20 74 6f 20 73 74 6f 72 65 20 53   need to store S
0ab0: 74 72 69 6e 67 20 6c 6f 63 61 6c 6c 79 20 74 6f  tring locally to
0ac0: 20 62 6f 72 72 6f 77 20 69 74 20 61 66 74 65 72   borrow it after
0ad0: 0a 09 09 6c 65 74 20 6d 75 74 20 6c 69 6e 6b 20  ...let mut link 
0ae0: 3d 20 6e 61 6d 65 3b 0a 09 09 6c 65 74 20 6e 61  = name;...let na
0af0: 6d 65 3a 20 53 74 72 69 6e 67 3b 0a 09 09 69 66  me: String;...if
0b00: 20 6c 65 74 20 53 6f 6d 65 28 63 61 70 73 29 20   let Some(caps) 
0b10: 3d 20 73 65 6c 66 2e 61 64 64 72 65 73 73 2e 63  = self.address.c
0b20: 61 70 74 75 72 65 73 28 6c 69 6e 6b 29 20 7b 0a  aptures(link) {.
0b30: 09 09 09 6e 61 6d 65 20 3d 20 63 61 70 73 5b 22  ...name = caps["
0b40: 6e 61 6d 65 22 5d 2e 74 6f 5f 73 74 72 69 6e 67  name"].to_string
0b50: 28 29 3b 0a 09 09 09 6c 69 6e 6b 20 3d 20 26 6e  ();....link = &n
0b60: 61 6d 65 3b 0a 09 09 7d 0a 09 09 6d 61 74 63 68  ame;...}...match
0b70: 20 73 65 6c 66 2e 74 67 2e 67 65 74 28 6c 69 6e   self.tg.get(lin
0b80: 6b 29 20 7b 0a 09 09 09 4f 6b 28 61 64 64 72 29  k) {....Ok(addr)
0b90: 20 3d 3e 20 4f 6b 28 61 64 64 72 29 2c 0a 09 09   => Ok(addr),...
0ba0: 09 45 72 72 28 5f 29 20 3d 3e 20 4f 6b 28 26 73  .Err(_) => Ok(&s
0bb0: 65 6c 66 2e 74 67 2e 64 65 66 61 75 6c 74 29 2c  elf.tg.default),
0bc0: 0a 09 09 7d 0a 09 7d 0a 0a 09 2f 2f 2f 20 41 74  ...}..}.../// At
0bd0: 74 65 6d 70 74 20 74 6f 20 64 65 6c 69 76 65 72  tempt to deliver
0be0: 20 6f 6e 65 20 6d 65 73 73 61 67 65 0a 09 61 73   one message..as
0bf0: 79 6e 63 20 66 6e 20 72 65 6c 61 79 5f 6d 61 69  ync fn relay_mai
0c00: 6c 20 28 26 73 65 6c 66 29 20 2d 3e 20 52 65 73  l (&self) -> Res
0c10: 75 6c 74 3c 28 29 3e 20 7b 0a 09 09 69 66 20 6c  ult<()> {...if l
0c20: 65 74 20 53 6f 6d 65 28 68 65 61 64 65 72 73 29  et Some(headers)
0c30: 20 3d 20 26 73 65 6c 66 2e 68 65 61 64 65 72 73   = &self.headers
0c40: 20 7b 0a 09 09 09 6c 65 74 20 6d 61 69 6c 20 3d   {....let mail =
0c50: 20 6d 61 69 6c 5f 70 61 72 73 65 72 3a 3a 4d 65   mail_parser::Me
0c60: 73 73 61 67 65 50 61 72 73 65 72 3a 3a 6e 65 77  ssageParser::new
0c70: 28 29 2e 70 61 72 73 65 28 26 73 65 6c 66 2e 64  ().parse(&self.d
0c80: 61 74 61 29 0a 09 09 09 09 2e 63 6f 6e 74 65 78  ata)......contex
0c90: 74 28 22 46 61 69 6c 65 64 20 74 6f 20 70 61 72  t("Failed to par
0ca0: 73 65 20 6d 61 69 6c 2e 22 29 3f 3b 0a 0a 09 09  se mail.")?;....
0cb0: 09 2f 2f 20 41 64 64 69 6e 67 20 61 6c 6c 20 6b  .// Adding all k
0cc0: 6e 6f 77 6e 20 61 64 64 72 65 73 73 65 73 20 74  nown addresses t
0cd0: 6f 20 72 65 63 69 70 69 65 6e 74 20 6c 69 73 74  o recipient list
0ce0: 2c 20 66 6f 72 20 61 6e 79 6f 6e 65 20 65 6c 73  , for anyone els
0cf0: 65 20 61 64 64 69 6e 67 20 64 65 66 61 75 6c 74  e adding default
0d00: 0a 09 09 09 2f 2f 20 41 6c 73 6f 20 69 66 20 6c  ....// Also if l
0d10: 69 73 74 20 69 73 20 65 6d 70 74 79 20 61 6c 73  ist is empty als
0d20: 6f 20 61 64 64 69 6e 67 20 64 65 66 61 75 6c 74  o adding default
0d30: 0a 09 09 09 6c 65 74 20 6d 75 74 20 72 63 70 74  ....let mut rcpt
0d40: 3a 20 48 61 73 68 53 65 74 3c 26 43 68 61 74 50  : HashSet<&ChatP
0d50: 65 65 72 49 64 3e 20 3d 20 48 61 73 68 53 65 74  eerId> = HashSet
0d60: 3a 3a 6e 65 77 28 29 3b 0a 09 09 09 69 66 20 68  ::new();....if h
0d70: 65 61 64 65 72 73 2e 74 6f 2e 69 73 5f 65 6d 70  eaders.to.is_emp
0d80: 74 79 28 29 20 26 26 20 21 73 65 6c 66 2e 72 65  ty() && !self.re
0d90: 6c 61 79 20 7b 0a 09 09 09 09 62 61 69 6c 21 28  lay {.....bail!(
0da0: 22 52 65 6c 61 79 69 6e 67 20 69 73 20 64 69 73  "Relaying is dis
0db0: 61 62 6c 65 64 2c 20 61 6e 64 20 74 68 65 72 65  abled, and there
0dc0: 27 73 20 6e 6f 20 64 65 73 74 69 6e 61 74 69 6f  's no destinatio
0dd0: 6e 20 61 64 64 72 65 73 73 22 29 3b 0a 09 09 09  n address");....
0de0: 7d 0a 09 09 09 66 6f 72 20 69 74 65 6d 20 69 6e  }....for item in
0df0: 20 26 68 65 61 64 65 72 73 2e 74 6f 20 7b 0a 09   &headers.to {..
0e00: 09 09 09 72 63 70 74 2e 69 6e 73 65 72 74 28 73  ...rcpt.insert(s
0e10: 65 6c 66 2e 67 65 74 5f 69 64 28 69 74 65 6d 29  elf.get_id(item)
0e20: 3f 29 3b 0a 09 09 09 7d 3b 0a 09 09 09 69 66 20  ?);....};....if 
0e30: 72 63 70 74 2e 69 73 5f 65 6d 70 74 79 28 29 20  rcpt.is_empty() 
0e40: 7b 0a 09 09 09 09 73 65 6c 66 2e 74 67 2e 64 65  {.....self.tg.de
0e50: 62 75 67 28 22 4e 6f 20 72 65 63 69 70 69 65 6e  bug("No recipien
0e60: 74 20 6f 72 20 65 6e 76 65 6c 6f 70 65 20 61 64  t or envelope ad
0e70: 64 72 65 73 73 2e 22 29 2e 61 77 61 69 74 3f 3b  dress.").await?;
0e80: 0a 09 09 09 09 72 63 70 74 2e 69 6e 73 65 72 74  .....rcpt.insert
0e90: 28 26 73 65 6c 66 2e 74 67 2e 64 65 66 61 75 6c  (&self.tg.defaul
0ea0: 74 29 3b 0a 09 09 09 7d 3b 0a 0a 09 09 09 2f 2f  t);....};.....//
0eb0: 20 70 72 65 70 61 72 69 6e 67 20 6d 65 73 73 61   preparing messa
0ec0: 67 65 20 68 65 61 64 65 72 0a 09 09 09 6c 65 74  ge header....let
0ed0: 20 6d 75 74 20 72 65 70 6c 79 3a 20 56 65 63 3c   mut reply: Vec<
0ee0: 53 74 72 69 6e 67 3e 20 3d 20 76 65 63 21 5b 22  String> = vec!["
0ef0: 3c 62 6c 6f 63 6b 71 75 6f 74 65 20 65 78 70 61  <blockquote expa
0f00: 6e 64 61 62 6c 65 3e 22 2e 69 6e 74 6f 28 29 5d  ndable>".into()]
0f10: 3b 0a 09 09 09 69 66 20 73 65 6c 66 2e 66 69 65  ;....if self.fie
0f20: 6c 64 73 2e 63 6f 6e 74 61 69 6e 73 28 22 73 75  lds.contains("su
0f30: 62 6a 65 63 74 22 29 20 7b 0a 09 09 09 09 69 66  bject") {.....if
0f40: 20 6c 65 74 20 53 6f 6d 65 28 73 75 62 6a 65 63   let Some(subjec
0f50: 74 29 20 3d 20 6d 61 69 6c 2e 73 75 62 6a 65 63  t) = mail.subjec
0f60: 74 28 29 20 7b 0a 09 09 09 09 09 72 65 70 6c 79  t() {......reply
0f70: 2e 70 75 73 68 28 66 6f 72 6d 61 74 21 28 22 3c  .push(format!("<
0f80: 75 3e 3c 69 3e 53 75 62 6a 65 63 74 3a 3c 2f 69  u><i>Subject:</i
0f90: 3e 3c 2f 75 3e e2 80 87 3c 63 6f 64 65 3e 7b 7d  ></u> <code>{}
0fa0: 3c 2f 63 6f 64 65 3e 22 2c 20 76 61 6c 69 64 61  </code>", valida
0fb0: 74 65 28 73 75 62 6a 65 63 74 29 2e 73 74 61 63  te(subject).stac
0fc0: 6b 28 29 3f 29 29 3b 0a 09 09 09 09 7d 20 65 6c  k()?));.....} el
0fd0: 73 65 20 69 66 20 6c 65 74 20 53 6f 6d 65 28 74  se if let Some(t
0fe0: 68 72 65 61 64 29 20 3d 20 6d 61 69 6c 2e 74 68  hread) = mail.th
0ff0: 72 65 61 64 5f 6e 61 6d 65 28 29 20 7b 0a 09 09  read_name() {...
1000: 09 09 09 72 65 70 6c 79 2e 70 75 73 68 28 66 6f  ...reply.push(fo
1010: 72 6d 61 74 21 28 22 3c 75 3e 3c 69 3e 54 68 72  rmat!("<u><i>Thr
1020: 65 61 64 3a 3c 2f 69 3e 3c 2f 75 3e e2 80 87 3c  ead:</i></u> <
1030: 63 6f 64 65 3e 7b 7d 3c 2f 63 6f 64 65 3e 22 2c  code>{}</code>",
1040: 20 76 61 6c 69 64 61 74 65 28 74 68 72 65 61 64   validate(thread
1050: 29 2e 73 74 61 63 6b 28 29 3f 29 29 3b 0a 09 09  ).stack()?));...
1060: 09 09 7d 0a 09 09 09 7d 0a 09 09 09 2f 2f 20 64  ..}....}....// d
1070: 6f 20 77 65 20 6e 65 65 64 20 74 6f 20 72 65 70  o we need to rep
1080: 6c 61 63 65 20 73 70 61 63 65 73 20 68 65 72 65  lace spaces here
1090: 3f 0a 09 09 09 69 66 20 73 65 6c 66 2e 66 69 65  ?....if self.fie
10a0: 6c 64 73 2e 63 6f 6e 74 61 69 6e 73 28 22 66 72  lds.contains("fr
10b0: 6f 6d 22 29 20 7b 0a 09 09 09 09 72 65 70 6c 79  om") {.....reply
10c0: 2e 70 75 73 68 28 66 6f 72 6d 61 74 21 28 22 3c  .push(format!("<
10d0: 75 3e 3c 69 3e 46 72 6f 6d 3a 3c 2f 69 3e 3c 2f  u><i>From:</i></
10e0: 75 3e e2 80 87 3c 63 6f 64 65 3e 7b 7d 3c 2f 63  u> <code>{}</c
10f0: 6f 64 65 3e 22 2c 20 76 61 6c 69 64 61 74 65 28  ode>", validate(
1100: 26 68 65 61 64 65 72 73 2e 66 72 6f 6d 29 2e 73  &headers.from).s
1110: 74 61 63 6b 28 29 3f 29 29 3b 0a 09 09 09 7d 0a  tack()?));....}.
1120: 09 09 09 69 66 20 73 65 6c 66 2e 66 69 65 6c 64  ...if self.field
1130: 73 2e 63 6f 6e 74 61 69 6e 73 28 22 64 61 74 65  s.contains("date
1140: 22 29 0a 09 09 09 09 26 26 20 6c 65 74 20 53 6f  ").....&& let So
1150: 6d 65 28 64 61 74 65 29 20 3d 20 6d 61 69 6c 2e  me(date) = mail.
1160: 64 61 74 65 28 29 0a 09 09 09 7b 0a 09 09 09 09  date()....{.....
1170: 72 65 70 6c 79 2e 70 75 73 68 28 66 6f 72 6d 61  reply.push(forma
1180: 74 21 28 22 3c 75 3e 3c 69 3e 44 61 74 65 3a 3c  t!("<u><i>Date:<
1190: 2f 69 3e 3c 2f 75 3e e2 80 87 3c 63 6f 64 65 3e  /i></u> <code>
11a0: 7b 64 61 74 65 7d 3c 2f 63 6f 64 65 3e 22 29 29  {date}</code>"))
11b0: 3b 0a 09 09 09 7d 0a 09 09 09 72 65 70 6c 79 2e  ;....}....reply.
11c0: 70 75 73 68 28 22 3c 2f 62 6c 6f 63 6b 71 75 6f  push("</blockquo
11d0: 74 65 3e 3c 70 72 65 3e 22 2e 69 6e 74 6f 28 29  te><pre>".into()
11e0: 29 3b 0a 09 09 09 2f 2f 6c 65 74 20 68 65 61 64  );....//let head
11f0: 65 72 5f 73 69 7a 65 20 3d 20 72 65 70 6c 79 2e  er_size = reply.
1200: 6a 6f 69 6e 28 22 20 22 29 2e 6c 65 6e 28 29 3b  join(" ").len();
1210: 0a 09 09 09 6c 65 74 20 6d 75 74 20 68 65 61 64  ....let mut head
1220: 65 72 5f 73 69 7a 65 20 3d 20 30 3b 0a 09 09 09  er_size = 0;....
1230: 66 6f 72 20 69 20 69 6e 20 72 65 70 6c 79 2e 69  for i in reply.i
1240: 74 65 72 28 29 20 7b 0a 09 09 09 09 68 65 61 64  ter() {.....head
1250: 65 72 5f 73 69 7a 65 20 2b 3d 20 69 2e 6c 65 6e  er_size += i.len
1260: 28 29 20 2b 20 31 3b 0a 09 09 09 7d 0a 0a 09 09  () + 1;....}....
1270: 09 6c 65 74 20 68 74 6d 6c 5f 70 61 72 74 73 20  .let html_parts 
1280: 3d 20 6d 61 69 6c 2e 68 74 6d 6c 5f 62 6f 64 79  = mail.html_body
1290: 5f 63 6f 75 6e 74 28 29 3b 0a 09 09 09 6c 65 74  _count();....let
12a0: 20 74 65 78 74 5f 70 61 72 74 73 20 3d 20 6d 61   text_parts = ma
12b0: 69 6c 2e 74 65 78 74 5f 62 6f 64 79 5f 63 6f 75  il.text_body_cou
12c0: 6e 74 28 29 3b 0a 09 09 09 6c 65 74 20 61 74 74  nt();....let att
12d0: 61 63 68 6d 65 6e 74 73 20 3d 20 6d 61 69 6c 2e  achments = mail.
12e0: 61 74 74 61 63 68 6d 65 6e 74 5f 63 6f 75 6e 74  attachment_count
12f0: 28 29 3b 0a 09 09 09 69 66 20 68 74 6d 6c 5f 70  ();....if html_p
1300: 61 72 74 73 20 21 3d 20 74 65 78 74 5f 70 61 72  arts != text_par
1310: 74 73 20 7b 0a 09 09 09 09 73 65 6c 66 2e 74 67  ts {.....self.tg
1320: 2e 64 65 62 75 67 28 26 66 6f 72 6d 61 74 21 28  .debug(&format!(
1330: 22 48 6d 2c 20 77 65 20 68 61 76 65 20 7b 68 74  "Hm, we have {ht
1340: 6d 6c 5f 70 61 72 74 73 7d 20 48 54 4d 4c 20 70  ml_parts} HTML p
1350: 61 72 74 73 20 61 6e 64 20 7b 74 65 78 74 5f 70  arts and {text_p
1360: 61 72 74 73 7d 20 74 65 78 74 20 70 61 72 74 73  arts} text parts
1370: 2e 22 29 29 2e 61 77 61 69 74 3f 3b 0a 09 09 09  .")).await?;....
1380: 7d 0a 09 09 09 2f 2f 6c 65 74 20 6d 75 74 20 68  }....//let mut h
1390: 74 6d 6c 5f 6e 75 6d 20 3d 20 30 3b 0a 09 09 09  tml_num = 0;....
13a0: 6c 65 74 20 6d 75 74 20 74 65 78 74 5f 6e 75 6d  let mut text_num
13b0: 20 3d 20 30 3b 0a 09 09 09 6c 65 74 20 6d 75 74   = 0;....let mut
13c0: 20 66 69 6c 65 5f 6e 75 6d 20 3d 20 30 3b 0a 09   file_num = 0;..
13d0: 09 09 2f 2f 20 6c 65 74 27 73 20 64 69 73 70 6c  ..// let's displ
13e0: 61 79 20 66 69 72 73 74 20 68 74 6d 6c 20 6f 72  ay first html or
13f0: 20 74 65 78 74 20 70 61 72 74 20 61 73 20 62 6f   text part as bo
1400: 64 79 0a 09 09 09 6c 65 74 20 6d 75 74 20 62 6f  dy....let mut bo
1410: 64 79 3a 20 43 6f 77 3c 27 5f 2c 20 73 74 72 3e  dy: Cow<'_, str>
1420: 20 3d 20 22 22 2e 69 6e 74 6f 28 29 3b 0a 09 09   = "".into();...
1430: 09 2f 2a 0a 09 09 09 20 2a 20 61 63 74 75 61 6c  ./*.... * actual
1440: 6c 79 20 49 20 64 6f 6e 27 74 20 77 61 6e 6e 61  ly I don't wanna
1450: 20 70 61 72 73 65 20 74 68 61 74 20 68 74 6d 6c   parse that html
1460: 20 73 74 75 66 66 0a 09 09 09 69 66 20 68 74 6d   stuff....if htm
1470: 6c 5f 70 61 72 74 73 20 3e 20 30 20 7b 0a 09 09  l_parts > 0 {...
1480: 09 09 6c 65 74 20 74 65 78 74 20 3d 20 6d 61 69  ..let text = mai
1490: 6c 2e 62 6f 64 79 5f 68 74 6d 6c 28 30 29 2e 73  l.body_html(0).s
14a0: 74 61 63 6b 28 29 3f 3b 0a 09 09 09 09 69 66 20  tack()?;.....if 
14b0: 74 65 78 74 2e 6c 65 6e 28 29 20 3c 20 34 30 39  text.len() < 409
14c0: 36 20 2d 20 68 65 61 64 65 72 5f 73 69 7a 65 20  6 - header_size 
14d0: 7b 0a 09 09 09 09 09 62 6f 64 79 20 3d 20 74 65  {......body = te
14e0: 78 74 3b 0a 09 09 09 09 09 68 74 6d 6c 5f 6e 75  xt;......html_nu
14f0: 6d 20 3d 20 31 3b 0a 09 09 09 09 7d 0a 09 09 09  m = 1;.....}....
1500: 7d 3b 0a 09 09 09 2a 2f 0a 09 09 09 69 66 20 62  };....*/....if b
1510: 6f 64 79 2e 69 73 5f 65 6d 70 74 79 28 29 20 26  ody.is_empty() &
1520: 26 20 74 65 78 74 5f 70 61 72 74 73 20 3e 20 30  & text_parts > 0
1530: 20 7b 0a 09 09 09 09 6c 65 74 20 74 65 78 74 20   {.....let text 
1540: 3d 20 6d 61 69 6c 2e 62 6f 64 79 5f 74 65 78 74  = mail.body_text
1550: 28 30 29 0a 09 09 09 09 09 2e 63 6f 6e 74 65 78  (0).......contex
1560: 74 28 22 46 61 69 6c 65 64 20 74 6f 20 65 78 74  t("Failed to ext
1570: 72 61 63 74 20 74 65 78 74 20 66 72 6f 6d 20 6d  ract text from m
1580: 65 73 73 61 67 65 22 29 3f 3b 0a 09 09 09 09 2f  essage")?;...../
1590: 2f 20 37 3a 0a 09 09 09 09 2f 2f 20 2d 20 28 6d  / 7:.....// - (m
15a0: 61 69 6c 20 74 65 78 74 29 0a 09 09 09 09 2f 2f  ail text).....//
15b0: 20 2d 20 31 20 74 72 61 69 6c 69 6e 67 20 6e 65   - 1 trailing ne
15c0: 77 6c 69 6e 65 0a 09 09 09 09 2f 2f 20 2d 20 36  wline.....// - 6
15d0: 3a 20 3c 2f 70 72 65 3e 0a 09 09 09 09 69 66 20  : </pre>.....if 
15e0: 74 65 78 74 2e 6c 65 6e 28 29 20 3c 20 34 30 39  text.len() < 409
15f0: 36 20 2d 20 28 20 68 65 61 64 65 72 5f 73 69 7a  6 - ( header_siz
1600: 65 20 2b 20 37 20 29 20 7b 0a 09 09 09 09 09 62  e + 7 ) {......b
1610: 6f 64 79 20 3d 20 74 65 78 74 3b 0a 09 09 09 09  ody = text;.....
1620: 09 74 65 78 74 5f 6e 75 6d 20 3d 20 31 3b 0a 09  .text_num = 1;..
1630: 09 09 09 7d 0a 09 09 09 7d 3b 0a 09 09 09 72 65  ...}....};....re
1640: 70 6c 79 2e 65 78 74 65 6e 64 28 62 6f 64 79 2e  ply.extend(body.
1650: 6c 69 6e 65 73 28 29 2e 6d 61 70 28 7c 78 7c 20  lines().map(|x| 
1660: 78 2e 69 6e 74 6f 28 29 29 29 3b 0a 09 09 09 72  x.into()));....r
1670: 65 70 6c 79 2e 70 75 73 68 28 22 3c 2f 70 72 65  eply.push("</pre
1680: 3e 22 2e 69 6e 74 6f 28 29 29 3b 0a 0a 09 09 09  >".into());.....
1690: 2f 2f 20 61 6e 64 20 6c 65 74 27 73 20 63 6f 6c  // and let's col
16a0: 6c 65 63 74 20 61 6c 6c 20 6f 74 68 65 72 20 61  lect all other a
16b0: 74 74 61 63 68 6d 65 6e 74 20 70 61 72 74 73 0a  ttachment parts.
16c0: 09 09 09 6c 65 74 20 6d 75 74 20 66 69 6c 65 73  ...let mut files
16d0: 5f 74 6f 5f 73 65 6e 64 20 3d 20 76 65 63 21 5b  _to_send = vec![
16e0: 5d 3b 0a 09 09 09 2f 2a 0a 09 09 09 20 2a 20 6c  ];..../*.... * l
16f0: 65 74 27 73 20 6a 75 73 74 20 73 6b 69 70 20 68  et's just skip h
1700: 74 6d 6c 20 70 61 72 74 73 20 66 6f 72 20 6e 6f  tml parts for no
1710: 77 2c 20 74 68 65 79 20 6a 75 73 74 20 64 75 70  w, they just dup
1720: 6c 69 63 61 74 65 20 74 65 78 74 3f 0a 09 09 09  licate text?....
1730: 77 68 69 6c 65 20 68 74 6d 6c 5f 6e 75 6d 20 3c  while html_num <
1740: 20 68 74 6d 6c 5f 70 61 72 74 73 20 7b 0a 09 09   html_parts {...
1750: 09 09 66 69 6c 65 73 5f 74 6f 5f 73 65 6e 64 2e  ..files_to_send.
1760: 70 75 73 68 28 6d 61 69 6c 2e 68 74 6d 6c 5f 70  push(mail.html_p
1770: 61 72 74 28 68 74 6d 6c 5f 6e 75 6d 29 2e 73 74  art(html_num).st
1780: 61 63 6b 28 29 3f 29 3b 0a 09 09 09 09 68 74 6d  ack()?);.....htm
1790: 6c 5f 6e 75 6d 20 2b 3d 20 31 3b 0a 09 09 09 7d  l_num += 1;....}
17a0: 0a 09 09 09 2a 2f 0a 09 09 09 77 68 69 6c 65 20  ....*/....while 
17b0: 74 65 78 74 5f 6e 75 6d 20 3c 20 74 65 78 74 5f  text_num < text_
17c0: 70 61 72 74 73 20 7b 0a 09 09 09 09 66 69 6c 65  parts {.....file
17d0: 73 5f 74 6f 5f 73 65 6e 64 2e 70 75 73 68 28 6d  s_to_send.push(m
17e0: 61 69 6c 2e 74 65 78 74 5f 70 61 72 74 28 74 65  ail.text_part(te
17f0: 78 74 5f 6e 75 6d 2e 74 72 79 5f 69 6e 74 6f 28  xt_num.try_into(
1800: 29 2e 73 74 61 63 6b 28 29 3f 29 0a 09 09 09 09  ).stack()?).....
1810: 09 2e 63 6f 6e 74 65 78 74 28 22 46 61 69 6c 65  ..context("Faile
1820: 64 20 74 6f 20 67 65 74 20 74 65 78 74 20 70 61  d to get text pa
1830: 72 74 20 66 72 6f 6d 20 6d 65 73 73 61 67 65 2e  rt from message.
1840: 22 29 3f 29 3b 0a 09 09 09 09 74 65 78 74 5f 6e  ")?);.....text_n
1850: 75 6d 20 2b 3d 20 31 3b 0a 09 09 09 7d 0a 09 09  um += 1;....}...
1860: 09 77 68 69 6c 65 20 66 69 6c 65 5f 6e 75 6d 20  .while file_num 
1870: 3c 20 61 74 74 61 63 68 6d 65 6e 74 73 20 7b 0a  < attachments {.
1880: 09 09 09 09 66 69 6c 65 73 5f 74 6f 5f 73 65 6e  ....files_to_sen
1890: 64 2e 70 75 73 68 28 6d 61 69 6c 2e 61 74 74 61  d.push(mail.atta
18a0: 63 68 6d 65 6e 74 28 66 69 6c 65 5f 6e 75 6d 2e  chment(file_num.
18b0: 74 72 79 5f 69 6e 74 6f 28 29 2e 73 74 61 63 6b  try_into().stack
18c0: 28 29 3f 29 0a 09 09 09 09 09 2e 63 6f 6e 74 65  ()?).......conte
18d0: 78 74 28 22 46 61 69 6c 65 64 20 74 6f 20 67 65  xt("Failed to ge
18e0: 74 20 66 69 6c 65 20 70 61 72 74 20 66 72 6f 6d  t file part from
18f0: 20 6d 65 73 73 61 67 65 2e 22 29 3f 29 3b 0a 09   message.")?);..
1900: 09 09 09 66 69 6c 65 5f 6e 75 6d 20 2b 3d 20 31  ...file_num += 1
1910: 3b 0a 09 09 09 7d 0a 0a 09 09 09 6c 65 74 20 6d  ;....}.....let m
1920: 73 67 20 3d 20 72 65 70 6c 79 2e 6a 6f 69 6e 28  sg = reply.join(
1930: 22 5c 6e 22 29 3b 0a 09 09 09 66 6f 72 20 63 68  "\n");....for ch
1940: 61 74 20 69 6e 20 72 63 70 74 20 7b 0a 09 09 09  at in rcpt {....
1950: 09 69 66 20 21 66 69 6c 65 73 5f 74 6f 5f 73 65  .if !files_to_se
1960: 6e 64 2e 69 73 5f 65 6d 70 74 79 28 29 20 7b 0a  nd.is_empty() {.
1970: 09 09 09 09 09 6c 65 74 20 6d 75 74 20 66 69 6c  .....let mut fil
1980: 65 73 20 3d 20 76 65 63 21 5b 5d 3b 0a 09 09 09  es = vec![];....
1990: 09 09 2f 2f 20 6c 65 74 20 6d 75 74 20 66 69 72  ..// let mut fir
19a0: 73 74 5f 6f 6e 65 20 3d 20 74 72 75 65 3b 0a 09  st_one = true;..
19b0: 09 09 09 09 66 6f 72 20 63 68 75 6e 6b 20 69 6e  ....for chunk in
19c0: 20 26 66 69 6c 65 73 5f 74 6f 5f 73 65 6e 64 20   &files_to_send 
19d0: 7b 0a 09 09 09 09 09 09 6c 65 74 20 64 61 74 61  {.......let data
19e0: 3a 20 56 65 63 3c 75 38 3e 20 3d 20 63 68 75 6e  : Vec<u8> = chun
19f0: 6b 2e 63 6f 6e 74 65 6e 74 73 28 29 2e 74 6f 5f  k.contents().to_
1a00: 76 65 63 28 29 3b 0a 09 09 09 09 09 09 6c 65 74  vec();.......let
1a10: 20 6d 75 74 20 66 69 6c 65 6e 61 6d 65 3a 20 4f   mut filename: O
1a20: 70 74 69 6f 6e 3c 53 74 72 69 6e 67 3e 20 3d 20  ption<String> = 
1a30: 4e 6f 6e 65 3b 0a 09 09 09 09 09 09 66 6f 72 20  None;.......for 
1a40: 68 65 61 64 65 72 20 69 6e 20 63 68 75 6e 6b 2e  header in chunk.
1a50: 68 65 61 64 65 72 73 28 29 20 7b 0a 09 09 09 09  headers() {.....
1a60: 09 09 09 69 66 20 68 65 61 64 65 72 2e 6e 61 6d  ...if header.nam
1a70: 65 28 29 20 3d 3d 20 22 43 6f 6e 74 65 6e 74 2d  e() == "Content-
1a80: 54 79 70 65 22 20 7b 0a 09 09 09 09 09 09 09 09  Type" {.........
1a90: 6d 61 74 63 68 20 68 65 61 64 65 72 2e 76 61 6c  match header.val
1aa0: 75 65 28 29 20 7b 0a 09 09 09 09 09 09 09 09 09  ue() {..........
1ab0: 6d 61 69 6c 5f 70 61 72 73 65 72 3a 3a 48 65 61  mail_parser::Hea
1ac0: 64 65 72 56 61 6c 75 65 3a 3a 43 6f 6e 74 65 6e  derValue::Conten
1ad0: 74 54 79 70 65 28 63 6f 6e 74 65 6e 74 74 79 70  tType(contenttyp
1ae0: 65 29 20 3d 3e 20 7b 0a 09 09 09 09 09 09 09 09  e) => {.........
1af0: 09 09 69 66 20 6c 65 74 20 53 6f 6d 65 28 66 6e  ..if let Some(fn
1b00: 61 6d 65 29 20 3d 20 63 6f 6e 74 65 6e 74 74 79  ame) = contentty
1b10: 70 65 2e 61 74 74 72 69 62 75 74 65 28 22 6e 61  pe.attribute("na
1b20: 6d 65 22 29 20 7b 0a 09 09 09 09 09 09 09 09 09  me") {..........
1b30: 09 09 66 69 6c 65 6e 61 6d 65 20 3d 20 53 6f 6d  ..filename = Som
1b40: 65 28 66 6e 61 6d 65 2e 74 6f 5f 6f 77 6e 65 64  e(fname.to_owned
1b50: 28 29 29 3b 0a 09 09 09 09 09 09 09 09 09 09 7d  ());...........}
1b60: 0a 09 09 09 09 09 09 09 09 09 7d 2c 0a 09 09 09  ..........},....
1b70: 09 09 09 09 09 09 5f 20 3d 3e 20 7b 0a 09 09 09  ......_ => {....
1b80: 09 09 09 09 09 09 09 73 65 6c 66 2e 74 67 2e 64  .......self.tg.d
1b90: 65 62 75 67 28 22 41 74 74 61 63 68 6d 65 6e 74  ebug("Attachment
1ba0: 20 68 61 73 20 62 61 64 20 43 6f 6e 74 65 6e 74   has bad Content
1bb0: 54 79 70 65 20 68 65 61 64 65 72 2e 22 29 2e 61  Type header.").a
1bc0: 77 61 69 74 3f 3b 0a 09 09 09 09 09 09 09 09 09  wait?;..........
1bd0: 7d 2c 0a 09 09 09 09 09 09 09 09 7d 3b 0a 09 09  },.........};...
1be0: 09 09 09 09 09 7d 3b 0a 09 09 09 09 09 09 7d 3b  .....};.......};
1bf0: 0a 09 09 09 09 09 09 6c 65 74 20 66 69 6c 65 6e  .......let filen
1c00: 61 6d 65 20 3d 20 69 66 20 6c 65 74 20 53 6f 6d  ame = if let Som
1c10: 65 28 66 6e 61 6d 65 29 20 3d 20 66 69 6c 65 6e  e(fname) = filen
1c20: 61 6d 65 20 7b 0a 09 09 09 09 09 09 09 66 6e 61  ame {........fna
1c30: 6d 65 0a 09 09 09 09 09 09 7d 20 65 6c 73 65 20  me.......} else 
1c40: 7b 0a 09 09 09 09 09 09 09 22 41 74 74 61 63 68  {........"Attach
1c50: 6d 65 6e 74 2e 74 78 74 22 2e 69 6e 74 6f 28 29  ment.txt".into()
1c60: 0a 09 09 09 09 09 09 7d 3b 0a 09 09 09 09 09 09  .......};.......
1c70: 66 69 6c 65 73 2e 70 75 73 68 28 41 74 74 61 63  files.push(Attac
1c80: 68 6d 65 6e 74 20 7b 0a 09 09 09 09 09 09 09 64  hment {........d
1c90: 61 74 61 3a 20 43 75 72 73 6f 72 3a 3a 6e 65 77  ata: Cursor::new
1ca0: 28 64 61 74 61 29 2c 0a 09 09 09 09 09 09 09 6e  (data),........n
1cb0: 61 6d 65 3a 20 66 69 6c 65 6e 61 6d 65 2c 0a 09  ame: filename,..
1cc0: 09 09 09 09 09 7d 29 3b 0a 09 09 09 09 09 7d 0a  .....});......}.
1cd0: 09 09 09 09 09 73 65 6c 66 2e 74 67 2e 73 65 6e  .....self.tg.sen
1ce0: 64 67 72 6f 75 70 28 63 68 61 74 2c 20 66 69 6c  dgroup(chat, fil
1cf0: 65 73 2c 20 26 6d 73 67 29 2e 61 77 61 69 74 3f  es, &msg).await?
1d00: 3b 0a 09 09 09 09 7d 20 65 6c 73 65 20 7b 0a 09  ;.....} else {..
1d10: 09 09 09 09 73 65 6c 66 2e 74 67 2e 73 65 6e 64  ....self.tg.send
1d20: 28 63 68 61 74 2c 20 26 6d 73 67 29 2e 61 77 61  (chat, &msg).awa
1d30: 69 74 3f 3b 0a 09 09 09 09 7d 0a 09 09 09 7d 0a  it?;.....}....}.
1d40: 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 62 61  ..} else {....ba
1d50: 69 6c 21 28 22 52 65 71 75 69 72 65 64 20 68 65  il!("Required he
1d60: 61 64 65 72 73 20 77 65 72 65 20 6e 6f 74 20 66  aders were not f
1d70: 6f 75 6e 64 2e 22 29 3b 0a 09 09 7d 0a 09 09 4f  ound.");...}...O
1d80: 6b 28 28 29 29 0a 09 7d 0a 7d 0a 0a 69 6d 70 6c  k(())..}.}..impl
1d90: 20 6d 61 69 6c 69 6e 5f 65 6d 62 65 64 64 65 64   mailin_embedded
1da0: 3a 3a 48 61 6e 64 6c 65 72 20 66 6f 72 20 4d 61  ::Handler for Ma
1db0: 69 6c 53 65 72 76 65 72 20 7b 0a 09 2f 2f 2f 20  ilServer {../// 
1dc0: 4a 75 73 74 20 64 65 6e 79 20 6c 6f 67 69 6e 20  Just deny login 
1dd0: 61 75 74 68 0a 09 66 6e 20 61 75 74 68 5f 6c 6f  auth..fn auth_lo
1de0: 67 69 6e 20 28 26 6d 75 74 20 73 65 6c 66 2c 20  gin (&mut self, 
1df0: 5f 75 73 65 72 6e 61 6d 65 3a 20 26 73 74 72 2c  _username: &str,
1e00: 20 5f 70 61 73 73 77 6f 72 64 3a 20 26 73 74 72   _password: &str
1e10: 29 20 2d 3e 20 52 65 73 70 6f 6e 73 65 20 7b 0a  ) -> Response {.
1e20: 09 09 49 4e 56 41 4c 49 44 5f 43 52 45 44 45 4e  ..INVALID_CREDEN
1e30: 54 49 41 4c 53 0a 09 7d 0a 0a 09 2f 2f 2f 20 4a  TIALS..}.../// J
1e40: 75 73 74 20 64 65 6e 79 20 70 6c 61 69 6e 20 61  ust deny plain a
1e50: 75 74 68 0a 09 66 6e 20 61 75 74 68 5f 70 6c 61  uth..fn auth_pla
1e60: 69 6e 20 28 26 6d 75 74 20 73 65 6c 66 2c 20 5f  in (&mut self, _
1e70: 61 75 74 68 6f 72 69 7a 61 74 69 6f 6e 5f 69 64  authorization_id
1e80: 3a 20 26 73 74 72 2c 20 5f 61 75 74 68 65 6e 74  : &str, _authent
1e90: 69 63 61 74 69 6f 6e 5f 69 64 3a 20 26 73 74 72  ication_id: &str
1ea0: 2c 20 5f 70 61 73 73 77 6f 72 64 3a 20 26 73 74  , _password: &st
1eb0: 72 29 20 2d 3e 20 52 65 73 70 6f 6e 73 65 20 7b  r) -> Response {
1ec0: 0a 09 09 49 4e 56 41 4c 49 44 5f 43 52 45 44 45  ...INVALID_CREDE
1ed0: 4e 54 49 41 4c 53 0a 09 7d 0a 0a 09 2f 2f 2f 20  NTIALS..}.../// 
1ee0: 56 65 72 69 66 79 20 77 68 65 74 68 65 72 20 61  Verify whether a
1ef0: 64 64 72 65 73 73 20 69 73 20 64 65 6c 69 76 65  ddress is delive
1f00: 72 61 62 6c 65 0a 09 66 6e 20 72 63 70 74 20 28  rable..fn rcpt (
1f10: 26 6d 75 74 20 73 65 6c 66 2c 20 74 6f 3a 20 26  &mut self, to: &
1f20: 73 74 72 29 20 2d 3e 20 52 65 73 70 6f 6e 73 65  str) -> Response
1f30: 20 7b 0a 09 09 69 66 20 73 65 6c 66 2e 72 65 6c   {...if self.rel
1f40: 61 79 20 7b 0a 09 09 09 4f 4b 0a 09 09 7d 20 65  ay {....OK...} e
1f50: 6c 73 65 20 7b 0a 09 09 09 6d 61 74 63 68 20 73  lse {....match s
1f60: 65 6c 66 2e 67 65 74 5f 69 64 28 74 6f 29 20 7b  elf.get_id(to) {
1f70: 0a 09 09 09 09 4f 6b 28 5f 29 20 3d 3e 20 4f 4b  .....Ok(_) => OK
1f80: 2c 0a 09 09 09 09 45 72 72 28 5f 29 20 3d 3e 20  ,.....Err(_) => 
1f90: 7b 0a 09 09 09 09 09 69 66 20 73 65 6c 66 2e 72  {......if self.r
1fa0: 65 6c 61 79 20 7b 0a 09 09 09 09 09 09 4f 4b 0a  elay {.......OK.
1fb0: 09 09 09 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09  .....} else {...
1fc0: 09 09 09 09 4e 4f 5f 4d 41 49 4c 42 4f 58 0a 09  ....NO_MAILBOX..
1fd0: 09 09 09 09 7d 0a 09 09 09 09 7d 0a 09 09 09 7d  ....}.....}....}
1fe0: 0a 09 09 7d 0a 09 7d 0a 0a 09 2f 2f 2f 20 53 61  ...}..}.../// Sa
1ff0: 76 65 20 68 65 61 64 65 72 73 20 77 65 20 6e 65  ve headers we ne
2000: 65 64 0a 09 66 6e 20 64 61 74 61 5f 73 74 61 72  ed..fn data_star
2010: 74 20 28 26 6d 75 74 20 73 65 6c 66 2c 20 5f 64  t (&mut self, _d
2020: 6f 6d 61 69 6e 3a 20 26 73 74 72 2c 20 66 72 6f  omain: &str, fro
2030: 6d 3a 20 26 73 74 72 2c 20 5f 69 73 38 62 69 74  m: &str, _is8bit
2040: 3a 20 62 6f 6f 6c 2c 20 74 6f 3a 20 26 5b 53 74  : bool, to: &[St
2050: 72 69 6e 67 5d 29 20 2d 3e 20 52 65 73 70 6f 6e  ring]) -> Respon
2060: 73 65 20 7b 0a 09 09 73 65 6c 66 2e 68 65 61 64  se {...self.head
2070: 65 72 73 20 3d 20 53 6f 6d 65 28 53 6f 6d 65 48  ers = Some(SomeH
2080: 65 61 64 65 72 73 7b 0a 09 09 09 66 72 6f 6d 3a  eaders{....from:
2090: 20 66 72 6f 6d 2e 74 6f 5f 73 74 72 69 6e 67 28   from.to_string(
20a0: 29 2c 0a 09 09 09 74 6f 3a 20 74 6f 2e 74 6f 5f  ),....to: to.to_
20b0: 76 65 63 28 29 2c 0a 09 09 7d 29 3b 0a 09 09 4f  vec(),...});...O
20c0: 4b 0a 09 7d 0a 0a 09 2f 2f 2f 20 53 61 76 65 20  K..}.../// Save 
20d0: 63 68 75 6e 6b 28 3f 29 20 6f 66 20 64 61 74 61  chunk(?) of data
20e0: 0a 09 66 6e 20 64 61 74 61 20 28 26 6d 75 74 20  ..fn data (&mut 
20f0: 73 65 6c 66 2c 20 62 75 66 3a 20 26 5b 75 38 5d  self, buf: &[u8]
2100: 29 20 2d 3e 20 73 74 64 3a 3a 72 65 73 75 6c 74  ) -> std::result
2110: 3a 3a 52 65 73 75 6c 74 3c 28 29 2c 20 45 72 72  ::Result<(), Err
2120: 6f 72 3e 20 7b 0a 09 09 73 65 6c 66 2e 64 61 74  or> {...self.dat
2130: 61 2e 61 70 70 65 6e 64 28 62 75 66 2e 74 6f 5f  a.append(buf.to_
2140: 76 65 63 28 29 2e 61 73 5f 6d 75 74 28 29 29 3b  vec().as_mut());
2150: 0a 09 09 4f 6b 28 28 29 29 0a 09 7d 0a 0a 09 2f  ...Ok(())..}.../
2160: 2f 2f 20 41 74 74 65 6d 70 74 20 74 6f 20 73 65  // Attempt to se
2170: 6e 64 20 65 6d 61 69 6c 2c 20 72 65 74 75 72 6e  nd email, return
2180: 20 74 65 6d 70 6f 72 61 72 79 20 65 72 72 6f 72   temporary error
2190: 20 69 66 20 74 68 61 74 20 66 61 69 6c 73 0a 09   if that fails..
21a0: 66 6e 20 64 61 74 61 5f 65 6e 64 20 28 26 6d 75  fn data_end (&mu
21b0: 74 20 73 65 6c 66 29 20 2d 3e 20 52 65 73 70 6f  t self) -> Respo
21c0: 6e 73 65 20 7b 0a 09 09 6c 65 74 20 6d 75 74 20  nse {...let mut 
21d0: 72 65 73 75 6c 74 20 3d 20 4f 4b 3b 0a 09 09 73  result = OK;...s
21e0: 6d 6f 6c 3a 3a 62 6c 6f 63 6b 5f 6f 6e 28 43 6f  mol::block_on(Co
21f0: 6d 70 61 74 3a 3a 6e 65 77 28 61 73 79 6e 63 20  mpat::new(async 
2200: 7b 0a 09 09 09 2f 2f 20 72 65 6c 61 79 20 6d 61  {....// relay ma
2210: 69 6c 0a 09 09 09 69 66 20 6c 65 74 20 45 72 72  il....if let Err
2220: 28 65 72 72 29 20 3d 20 73 65 6c 66 2e 72 65 6c  (err) = self.rel
2230: 61 79 5f 6d 61 69 6c 28 29 2e 61 77 61 69 74 20  ay_mail().await 
2240: 7b 0a 09 09 09 09 72 65 73 75 6c 74 20 3d 20 49  {.....result = I
2250: 4e 54 45 52 4e 41 4c 5f 45 52 52 4f 52 3b 0a 09  NTERNAL_ERROR;..
2260: 09 09 09 2f 2f 20 69 6e 20 63 61 73 65 20 74 68  ...// in case th
2270: 61 74 20 66 61 69 6c 73 20 2d 20 69 6e 66 6f 72  at fails - infor
2280: 6d 20 64 65 66 61 75 6c 74 20 72 65 63 69 70 69  m default recipi
2290: 65 6e 74 0a 09 09 09 09 69 66 20 6c 65 74 20 45  ent.....if let E
22a0: 72 72 28 65 72 72 29 20 3d 20 73 65 6c 66 2e 74  rr(err) = self.t
22b0: 67 2e 64 65 62 75 67 28 26 66 6f 72 6d 61 74 21  g.debug(&format!
22c0: 28 22 53 65 6e 64 69 6e 67 20 65 6d 61 69 6c 73  ("Sending emails
22d0: 20 66 61 69 6c 65 64 3a 5c 6e 7b 65 72 72 3a 3f   failed:\n{err:?
22e0: 7d 22 29 29 2e 61 77 61 69 74 20 7b 0a 09 09 09  }")).await {....
22f0: 09 09 2f 2f 20 69 6e 20 63 61 73 65 20 74 68 61  ..// in case tha
2300: 74 20 61 6c 73 6f 20 66 61 69 6c 73 20 2d 20 77  t also fails - w
2310: 72 69 74 65 20 73 6f 6d 65 20 6c 6f 67 73 20 61  rite some logs a
2320: 6e 64 20 62 61 69 6c 0a 09 09 09 09 09 65 70 72  nd bail......epr
2330: 69 6e 74 6c 6e 21 28 22 7b 65 72 72 3a 3f 7d 22  intln!("{err:?}"
2340: 29 3b 0a 09 09 09 09 7d 3b 0a 09 09 09 7d 3b 0a  );.....};....};.
2350: 09 09 7d 29 29 3b 0a 09 09 2f 2f 20 63 6c 65 61  ..}));...// clea
2360: 72 20 2d 20 6a 75 73 74 20 69 6e 20 63 61 73 65  r - just in case
2370: 0a 09 09 73 65 6c 66 2e 64 61 74 61 20 3d 20 76  ...self.data = v
2380: 65 63 21 5b 5d 3b 0a 09 09 73 65 6c 66 2e 68 65  ec![];...self.he
2390: 61 64 65 72 73 20 3d 20 4e 6f 6e 65 3b 0a 09 09  aders = None;...
23a0: 72 65 73 75 6c 74 0a 09 7d 0a 7d 0a              result..}.}.