diff --git a/server/src/graphql.rs b/server/src/graphql.rs index de7409e..2afdf56 100644 --- a/server/src/graphql.rs +++ b/server/src/graphql.rs @@ -23,6 +23,12 @@ pub type UnixTime = isize; /// # Thread ID, sans "thread:" pub type ThreadId = String; +const TEXT_PLAIN: &'static str = "text/plain"; +const TEXT_HTML: &'static str = "text/html"; +const MULTIPART_ALTERNATIVE: &'static str = "multipart/alternative"; +const MULTIPART_MIXED: &'static str = "multipart/mixed"; +const MULTIPART_RELATED: &'static str = "multipart/related"; + #[derive(Debug, SimpleObject)] pub struct ThreadSummary { pub thread: ThreadId, @@ -426,10 +432,10 @@ impl Mutation { fn extract_body(m: &ParsedMail) -> Result { let body = m.get_body()?; let ret = match m.ctype.mimetype.as_str() { - "text/plain" => return Ok(Body::text(body)), - "text/html" => return Ok(Body::html(body)), - "multipart/mixed" => extract_mixed(m), - "multipart/alternative" => extract_alternative(m), + TEXT_PLAIN => return Ok(Body::text(body)), + TEXT_HTML => return Ok(Body::html(body)), + MULTIPART_MIXED => extract_mixed(m), + MULTIPART_ALTERNATIVE => extract_alternative(m), _ => extract_unhandled(m), }; if let Err(err) = ret { @@ -444,7 +450,6 @@ fn extract_unhandled(m: &ParsedMail) -> Result { "Unhandled body content type:\n{}", render_content_type_tree(m) ); - warn!("{}", msg); Ok(Body::UnhandledContentType(UnhandledContentType { text: msg, })) @@ -455,59 +460,81 @@ fn extract_unhandled(m: &ParsedMail) -> Result { // then give up. fn extract_alternative(m: &ParsedMail) -> Result { for sp in &m.subparts { - if sp.ctype.mimetype == "text/html" { + if sp.ctype.mimetype.as_str() == TEXT_HTML { let body = sp.get_body()?; return Ok(Body::html(body)); } } for sp in &m.subparts { - if sp.ctype.mimetype == "text/plain" { + if sp.ctype.mimetype.as_str() == TEXT_PLAIN { let body = sp.get_body()?; return Ok(Body::text(body)); } } - Err("extract_alternative".into()) + for sp in &m.subparts { + if sp.ctype.mimetype.as_str() == MULTIPART_RELATED { + return extract_related(sp); + } + } + Err(format!( + "extract_alternative failed to find suitable subpart, searched: {:?}", + vec![TEXT_HTML, TEXT_PLAIN] + ) + .into()) } // multipart/mixed defines multiple types of context all of which should be presented to the user // 'serially'. fn extract_mixed(m: &ParsedMail) -> Result { for sp in &m.subparts { - if sp.ctype.mimetype == "multipart/alternative" { + if sp.ctype.mimetype.as_str() == MULTIPART_ALTERNATIVE { return extract_alternative(sp); } } for sp in &m.subparts { - if sp.ctype.mimetype == "multipart/related" { + if sp.ctype.mimetype == MULTIPART_RELATED { return extract_related(sp); } } for sp in &m.subparts { let body = sp.get_body()?; match sp.ctype.mimetype.as_str() { - "text/plain" => return Ok(Body::text(body)), - "text/html" => return Ok(Body::html(body)), + TEXT_PLAIN => return Ok(Body::text(body)), + TEXT_HTML => return Ok(Body::html(body)), _ => (), } } - Err("extract_mixed".into()) + Err(format!( + "extract_mixed failed to find suitable subpart, searched: {:?}", + vec![ + MULTIPART_ALTERNATIVE, + MULTIPART_RELATED, + TEXT_HTML, + TEXT_PLAIN + ] + ) + .into()) } fn extract_related(m: &ParsedMail) -> Result { // TODO(wathiede): collect related things and change return type to new Body arm. for sp in &m.subparts { - if sp.ctype.mimetype == "text/html" { + if sp.ctype.mimetype == TEXT_HTML { let body = sp.get_body()?; return Ok(Body::html(body)); } } for sp in &m.subparts { - if sp.ctype.mimetype == "text/plain" { + if sp.ctype.mimetype == TEXT_PLAIN { let body = sp.get_body()?; return Ok(Body::text(body)); } } - Err("extract_related".into()) + Err(format!( + "extract_related failed to find suitable subpart, searched: {:?}", + vec![TEXT_HTML, TEXT_PLAIN] + ) + .into()) } // TODO(wathiede): make this walk_attachments that takes a closure.