melib: refactor attachments and attachment_types interfaces
parent
7592e66d6a
commit
c17bb24f0d
|
@ -472,7 +472,7 @@ impl Envelope {
|
||||||
&& cst.eq_ignore_ascii_case(b"mixed") =>
|
&& cst.eq_ignore_ascii_case(b"mixed") =>
|
||||||
{
|
{
|
||||||
let mut builder = AttachmentBuilder::new(body);
|
let mut builder = AttachmentBuilder::new(body);
|
||||||
builder.set_content_type(value);
|
builder.set_content_type_from_bytes(value);
|
||||||
let b = builder.build();
|
let b = builder.build();
|
||||||
let subs = b.attachments();
|
let subs = b.attachments();
|
||||||
|
|
||||||
|
@ -586,9 +586,9 @@ impl Envelope {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if name.eq_ignore_ascii_case(b"content-transfer-encoding") {
|
if name.eq_ignore_ascii_case(b"content-transfer-encoding") {
|
||||||
builder.set_content_transfer_encoding(value);
|
builder.set_content_transfer_encoding(ContentTransferEncoding::from(value));
|
||||||
} else if name.eq_ignore_ascii_case(b"content-type") {
|
} else if name.eq_ignore_ascii_case(b"content-type") {
|
||||||
builder.set_content_type(value);
|
builder.set_content_type_from_bytes(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builder.build()
|
builder.build()
|
||||||
|
|
|
@ -1,30 +1,28 @@
|
||||||
|
/*
|
||||||
|
* meli
|
||||||
|
*
|
||||||
|
* Copyright 2017-2019 Manos Pitsidianakis
|
||||||
|
*
|
||||||
|
* This file is part of meli.
|
||||||
|
*
|
||||||
|
* meli is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* meli is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
use crate::email::attachments::Attachment;
|
use crate::email::attachments::Attachment;
|
||||||
use crate::email::parser::BytesExt;
|
use crate::email::parser::BytesExt;
|
||||||
use std::fmt::{Display, Formatter, Result as FmtResult};
|
use std::fmt::{Display, Formatter, Result as FmtResult};
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
// TODO: rename.
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Default)]
|
|
||||||
pub struct SliceBuild {
|
|
||||||
offset: usize,
|
|
||||||
end: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SliceBuild {
|
|
||||||
pub fn new(offset: usize, length: usize) -> Self {
|
|
||||||
SliceBuild {
|
|
||||||
offset,
|
|
||||||
end: offset + length,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//fn length(&self) -> usize {
|
|
||||||
// self.end - self.offset + 1
|
|
||||||
//}
|
|
||||||
pub fn get<'a>(&self, slice: &'a [u8]) -> &'a [u8] {
|
|
||||||
&slice[self.offset..self.end]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum Charset {
|
pub enum Charset {
|
||||||
Ascii,
|
Ascii,
|
||||||
|
@ -100,6 +98,22 @@ impl Display for MultipartType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&[u8]> for MultipartType {
|
||||||
|
fn from(val: &[u8]) -> MultipartType {
|
||||||
|
if val.eq_ignore_ascii_case(b"mixed") {
|
||||||
|
MultipartType::Mixed
|
||||||
|
} else if val.eq_ignore_ascii_case(b"alternative") {
|
||||||
|
MultipartType::Alternative
|
||||||
|
} else if val.eq_ignore_ascii_case(b"digest") {
|
||||||
|
MultipartType::Digest
|
||||||
|
} else if val.eq_ignore_ascii_case(b"signed") {
|
||||||
|
MultipartType::Signed
|
||||||
|
} else {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
pub enum ContentType {
|
pub enum ContentType {
|
||||||
Text {
|
Text {
|
||||||
|
@ -107,7 +121,7 @@ pub enum ContentType {
|
||||||
charset: Charset,
|
charset: Charset,
|
||||||
},
|
},
|
||||||
Multipart {
|
Multipart {
|
||||||
boundary: SliceBuild,
|
boundary: Vec<u8>,
|
||||||
kind: MultipartType,
|
kind: MultipartType,
|
||||||
subattachments: Vec<Attachment>,
|
subattachments: Vec<Attachment>,
|
||||||
},
|
},
|
||||||
|
@ -216,3 +230,20 @@ impl Display for ContentTransferEncoding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl From<&[u8]> for ContentTransferEncoding {
|
||||||
|
fn from(val: &[u8]) -> ContentTransferEncoding {
|
||||||
|
if val.eq_ignore_ascii_case(b"base64") {
|
||||||
|
ContentTransferEncoding::Base64
|
||||||
|
} else if val.eq_ignore_ascii_case(b"7bit") {
|
||||||
|
ContentTransferEncoding::_7Bit
|
||||||
|
} else if val.eq_ignore_ascii_case(b"8bit") {
|
||||||
|
ContentTransferEncoding::_8Bit
|
||||||
|
} else if val.eq_ignore_ascii_case(b"quoted-printable") {
|
||||||
|
ContentTransferEncoding::QuotedPrintable
|
||||||
|
} else {
|
||||||
|
ContentTransferEncoding::Other {
|
||||||
|
tag: val.to_ascii_lowercase(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -21,20 +21,12 @@
|
||||||
use crate::email::parser;
|
use crate::email::parser;
|
||||||
use crate::email::parser::BytesExt;
|
use crate::email::parser::BytesExt;
|
||||||
use crate::email::EnvelopeWrapper;
|
use crate::email::EnvelopeWrapper;
|
||||||
|
use core::fmt;
|
||||||
|
use core::str;
|
||||||
use data_encoding::BASE64_MIME;
|
use data_encoding::BASE64_MIME;
|
||||||
use std::fmt;
|
|
||||||
use std::str;
|
|
||||||
|
|
||||||
pub use crate::email::attachment_types::*;
|
pub use crate::email::attachment_types::*;
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Data
|
|
||||||
* Text { content: Vec<u8> }
|
|
||||||
* Multipart
|
|
||||||
*/
|
|
||||||
// TODO: Add example.
|
|
||||||
//
|
|
||||||
#[derive(Default, PartialEq)]
|
#[derive(Default, PartialEq)]
|
||||||
pub struct AttachmentBuilder {
|
pub struct AttachmentBuilder {
|
||||||
content_type: ContentType,
|
content_type: ContentType,
|
||||||
|
@ -42,30 +34,6 @@ pub struct AttachmentBuilder {
|
||||||
|
|
||||||
raw: Vec<u8>,
|
raw: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, PartialEq)]
|
|
||||||
pub struct Attachment {
|
|
||||||
content_type: ContentType,
|
|
||||||
content_transfer_encoding: ContentTransferEncoding,
|
|
||||||
|
|
||||||
raw: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Attachment {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "Attachment {{\n content_type: {:?},\n content_transfer_encoding: {:?},\n raw: Vec of {} bytes\n, body:\n{}\n}}",
|
|
||||||
self.content_type,
|
|
||||||
self.content_transfer_encoding,
|
|
||||||
self.raw.len(),
|
|
||||||
{
|
|
||||||
let mut text = Vec::with_capacity(4096);
|
|
||||||
self.get_text_recursive(&mut text);
|
|
||||||
std::str::from_utf8(&text).map(std::string::ToString::to_string).unwrap_or_else(|e| format!("Unicode error {}", e))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AttachmentBuilder {
|
impl AttachmentBuilder {
|
||||||
pub fn new(content: &[u8]) -> Self {
|
pub fn new(content: &[u8]) -> Self {
|
||||||
AttachmentBuilder {
|
AttachmentBuilder {
|
||||||
|
@ -74,11 +42,26 @@ impl AttachmentBuilder {
|
||||||
raw: content.to_vec(),
|
raw: content.to_vec(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn content_type(&mut self) -> &ContentType {
|
|
||||||
|
pub fn set_content_type(&mut self, val: ContentType) -> &mut Self {
|
||||||
|
self.content_type = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn content_type(&self) -> &ContentType {
|
||||||
&self.content_type
|
&self.content_type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_content_type(&mut self, value: &[u8]) -> &Self {
|
pub fn set_content_transfer_encoding(&mut self, val: ContentTransferEncoding) -> &mut Self {
|
||||||
|
self.content_transfer_encoding = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn content_transfer_encoding(&self) -> &ContentTransferEncoding {
|
||||||
|
&self.content_transfer_encoding
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_content_type_from_bytes(&mut self, value: &[u8]) -> &mut Self {
|
||||||
match parser::content_type(value).to_full_result() {
|
match parser::content_type(value).to_full_result() {
|
||||||
Ok((ct, cst, params)) => {
|
Ok((ct, cst, params)) => {
|
||||||
if ct.eq_ignore_ascii_case(b"multipart") {
|
if ct.eq_ignore_ascii_case(b"multipart") {
|
||||||
|
@ -90,26 +73,12 @@ impl AttachmentBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert!(boundary.is_some());
|
assert!(boundary.is_some());
|
||||||
let _boundary = boundary.unwrap();
|
let boundary = boundary.unwrap().to_vec();
|
||||||
let offset =
|
let subattachments = Self::subattachments(&self.raw, &boundary);
|
||||||
(_boundary.as_ptr() as usize).wrapping_sub(value.as_ptr() as usize);
|
|
||||||
let boundary = SliceBuild::new(offset, _boundary.len());
|
|
||||||
let subattachments = Self::subattachments(&self.raw, boundary.get(&value));
|
|
||||||
// Invalid mail or wrong assumption?
|
|
||||||
// assert!(!subattachments.is_empty());
|
|
||||||
self.content_type = ContentType::Multipart {
|
self.content_type = ContentType::Multipart {
|
||||||
boundary,
|
boundary,
|
||||||
kind: if cst.eq_ignore_ascii_case(b"mixed") {
|
kind: MultipartType::from(cst),
|
||||||
MultipartType::Mixed
|
|
||||||
} else if cst.eq_ignore_ascii_case(b"alternative") {
|
|
||||||
MultipartType::Alternative
|
|
||||||
} else if cst.eq_ignore_ascii_case(b"digest") {
|
|
||||||
MultipartType::Digest
|
|
||||||
} else if cst.eq_ignore_ascii_case(b"signed") {
|
|
||||||
MultipartType::Signed
|
|
||||||
} else {
|
|
||||||
Default::default()
|
|
||||||
},
|
|
||||||
subattachments,
|
subattachments,
|
||||||
};
|
};
|
||||||
} else if ct.eq_ignore_ascii_case(b"text") {
|
} else if ct.eq_ignore_ascii_case(b"text") {
|
||||||
|
@ -164,50 +133,7 @@ impl AttachmentBuilder {
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn set_content_transfer_encoding(&mut self, value: &[u8]) -> &Self {
|
|
||||||
self.content_transfer_encoding = if value.eq_ignore_ascii_case(b"base64") {
|
|
||||||
ContentTransferEncoding::Base64
|
|
||||||
} else if value.eq_ignore_ascii_case(b"7bit") {
|
|
||||||
ContentTransferEncoding::_7Bit
|
|
||||||
} else if value.eq_ignore_ascii_case(b"8bit") {
|
|
||||||
ContentTransferEncoding::_8Bit
|
|
||||||
} else if value.eq_ignore_ascii_case(b"quoted-printable") {
|
|
||||||
ContentTransferEncoding::QuotedPrintable
|
|
||||||
} else {
|
|
||||||
ContentTransferEncoding::Other {
|
|
||||||
tag: value.to_ascii_lowercase(),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
fn decode(&self) -> Vec<u8> {
|
|
||||||
// TODO merge this and standalone decode() function
|
|
||||||
let charset = match self.content_type {
|
|
||||||
ContentType::Text { charset: c, .. } => c,
|
|
||||||
_ => Default::default(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let bytes = match self.content_transfer_encoding {
|
|
||||||
ContentTransferEncoding::Base64 => match BASE64_MIME.decode(&self.raw) {
|
|
||||||
Ok(v) => v,
|
|
||||||
_ => self.raw.to_vec(),
|
|
||||||
},
|
|
||||||
ContentTransferEncoding::QuotedPrintable => parser::quoted_printable_bytes(&self.raw)
|
|
||||||
.to_full_result()
|
|
||||||
.unwrap(),
|
|
||||||
ContentTransferEncoding::_7Bit
|
|
||||||
| ContentTransferEncoding::_8Bit
|
|
||||||
| ContentTransferEncoding::Other { .. } => self.raw.to_vec(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Ok(b) = parser::decode_charset(&bytes, charset) {
|
|
||||||
b.into_bytes()
|
|
||||||
} else {
|
|
||||||
self.raw.to_vec()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
pub fn build(self) -> Attachment {
|
pub fn build(self) -> Attachment {
|
||||||
Attachment {
|
Attachment {
|
||||||
content_type: self.content_type,
|
content_type: self.content_type,
|
||||||
|
@ -234,16 +160,14 @@ impl AttachmentBuilder {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let body_slice = {
|
builder.raw = body.ltrim().into();
|
||||||
let offset = (body.as_ptr() as usize).wrapping_sub(a.as_ptr() as usize);
|
|
||||||
SliceBuild::new(offset, body.len())
|
|
||||||
};
|
|
||||||
builder.raw = body_slice.get(a).ltrim().into();
|
|
||||||
for (name, value) in headers {
|
for (name, value) in headers {
|
||||||
if name.eq_ignore_ascii_case(b"content-type") {
|
if name.eq_ignore_ascii_case(b"content-type") {
|
||||||
builder.set_content_type(value);
|
builder.set_content_type_from_bytes(value);
|
||||||
} else if name.eq_ignore_ascii_case(b"content-transfer-encoding") {
|
} else if name.eq_ignore_ascii_case(b"content-transfer-encoding") {
|
||||||
builder.set_content_transfer_encoding(value);
|
builder.set_content_transfer_encoding(ContentTransferEncoding::from(
|
||||||
|
value,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vec.push(builder.build());
|
vec.push(builder.build());
|
||||||
|
@ -263,10 +187,34 @@ impl AttachmentBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Immutable attachment type.
|
||||||
|
#[derive(Clone, Serialize, Deserialize, PartialEq)]
|
||||||
|
pub struct Attachment {
|
||||||
|
content_type: ContentType,
|
||||||
|
content_transfer_encoding: ContentTransferEncoding,
|
||||||
|
|
||||||
|
raw: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Attachment {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "Attachment {{\n content_type: {:?},\n content_transfer_encoding: {:?},\n raw: Vec of {} bytes\n, body:\n{}\n}}",
|
||||||
|
self.content_type,
|
||||||
|
self.content_transfer_encoding,
|
||||||
|
self.raw.len(),
|
||||||
|
{
|
||||||
|
let mut text = Vec::with_capacity(4096);
|
||||||
|
self.get_text_recursive(&mut text);
|
||||||
|
std::str::from_utf8(&text).map(std::string::ToString::to_string).unwrap_or_else(|e| format!("Unicode error {}", e))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for Attachment {
|
impl fmt::Display for Attachment {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self.content_type {
|
match self.content_type {
|
||||||
ContentType::MessageRfc822 => match EnvelopeWrapper::new(self.bytes().to_vec()) {
|
ContentType::MessageRfc822 => match EnvelopeWrapper::new(self.raw().to_vec()) {
|
||||||
Ok(wrapper) => write!(
|
Ok(wrapper) => write!(
|
||||||
f,
|
f,
|
||||||
"message/rfc822: {} - {} - {}",
|
"message/rfc822: {} - {} - {}",
|
||||||
|
@ -307,7 +255,7 @@ impl Attachment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bytes(&self) -> &[u8] {
|
pub fn raw(&self) -> &[u8] {
|
||||||
&self.raw
|
&self.raw
|
||||||
}
|
}
|
||||||
fn get_text_recursive(&self, text: &mut Vec<u8>) {
|
fn get_text_recursive(&self, text: &mut Vec<u8>) {
|
||||||
|
@ -442,27 +390,13 @@ impl Attachment {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interpret_format_flowed(_t: &str) -> String {
|
pub fn interpret_format_flowed(_t: &str) -> String {
|
||||||
//let mut n = String::with_capacity(t.len());
|
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_rfc822(_raw: &[u8]) -> Attachment {
|
fn decode_rfc822(_raw: &[u8]) -> Attachment {
|
||||||
let builder = AttachmentBuilder::new(b"");
|
// FIXME
|
||||||
|
let builder = AttachmentBuilder::new(b"message/rfc822 cannot be displayed");
|
||||||
builder.build()
|
builder.build()
|
||||||
|
|
||||||
/*
|
|
||||||
debug!("raw is\n{:?}", str::from_utf8(raw).unwrap());
|
|
||||||
let e = match Envelope::from_bytes(raw) {
|
|
||||||
Some(e) => e,
|
|
||||||
None => {
|
|
||||||
debug!("error in parsing mail");
|
|
||||||
let error_msg = b"Mail cannot be shown because of errors.";
|
|
||||||
let mut builder = AttachmentBuilder::new(error_msg);
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
e.body(None)
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Filter<'a> = Box<FnMut(&'a Attachment, &mut Vec<u8>) -> () + 'a>;
|
type Filter<'a> = Box<FnMut(&'a Attachment, &mut Vec<u8>) -> () + 'a>;
|
||||||
|
@ -514,23 +448,23 @@ fn decode_helper<'a>(a: &'a Attachment, filter: &mut Option<Filter<'a>>) -> Vec<
|
||||||
};
|
};
|
||||||
|
|
||||||
let bytes = match a.content_transfer_encoding {
|
let bytes = match a.content_transfer_encoding {
|
||||||
ContentTransferEncoding::Base64 => match BASE64_MIME.decode(a.bytes()) {
|
ContentTransferEncoding::Base64 => match BASE64_MIME.decode(a.raw()) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
_ => a.bytes().to_vec(),
|
_ => a.raw().to_vec(),
|
||||||
},
|
},
|
||||||
ContentTransferEncoding::QuotedPrintable => parser::quoted_printable_bytes(a.bytes())
|
ContentTransferEncoding::QuotedPrintable => parser::quoted_printable_bytes(a.raw())
|
||||||
.to_full_result()
|
.to_full_result()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
ContentTransferEncoding::_7Bit
|
ContentTransferEncoding::_7Bit
|
||||||
| ContentTransferEncoding::_8Bit
|
| ContentTransferEncoding::_8Bit
|
||||||
| ContentTransferEncoding::Other { .. } => a.bytes().to_vec(),
|
| ContentTransferEncoding::Other { .. } => a.raw().to_vec(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut ret = if a.content_type.is_text() {
|
let mut ret = if a.content_type.is_text() {
|
||||||
if let Ok(v) = parser::decode_charset(&bytes, charset) {
|
if let Ok(v) = parser::decode_charset(&bytes, charset) {
|
||||||
v.into_bytes()
|
v.into_bytes()
|
||||||
} else {
|
} else {
|
||||||
a.bytes().to_vec()
|
a.raw().to_vec()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bytes.to_vec()
|
bytes.to_vec()
|
||||||
|
|
|
@ -200,7 +200,7 @@ impl MailView {
|
||||||
}
|
}
|
||||||
t
|
t
|
||||||
}
|
}
|
||||||
ViewMode::Raw => String::from_utf8_lossy(body.bytes()).into_owned(),
|
ViewMode::Raw => String::from_utf8_lossy(body.raw()).into_owned(),
|
||||||
ViewMode::Url => {
|
ViewMode::Url => {
|
||||||
let mut t = body_text.to_string();
|
let mut t = body_text.to_string();
|
||||||
for (lidx, l) in finder.links(&body.text()).enumerate() {
|
for (lidx, l) in finder.links(&body.text()).enumerate() {
|
||||||
|
@ -720,7 +720,7 @@ impl Component for MailView {
|
||||||
match u.content_type() {
|
match u.content_type() {
|
||||||
ContentType::MessageRfc822 => {
|
ContentType::MessageRfc822 => {
|
||||||
self.mode = ViewMode::Subview;
|
self.mode = ViewMode::Subview;
|
||||||
match EnvelopeWrapper::new(u.bytes().to_vec()) {
|
match EnvelopeWrapper::new(u.raw().to_vec()) {
|
||||||
Ok(wrapper) => {
|
Ok(wrapper) => {
|
||||||
self.subview = Some(Box::new(EnvelopeView::new(
|
self.subview = Some(Box::new(EnvelopeView::new(
|
||||||
wrapper,
|
wrapper,
|
||||||
|
|
|
@ -150,7 +150,7 @@ impl EnvelopeView {
|
||||||
}
|
}
|
||||||
t
|
t
|
||||||
}
|
}
|
||||||
ViewMode::Raw => String::from_utf8_lossy(body.bytes()).into_owned(),
|
ViewMode::Raw => String::from_utf8_lossy(body.raw()).into_owned(),
|
||||||
ViewMode::Url => {
|
ViewMode::Url => {
|
||||||
let mut t = body_text.to_string();
|
let mut t = body_text.to_string();
|
||||||
for (lidx, l) in finder.links(&body.text()).enumerate() {
|
for (lidx, l) in finder.links(&body.text()).enumerate() {
|
||||||
|
|
Loading…
Reference in New Issue