Code Monkey home page Code Monkey logo

rust-email's People

Contributors

amousset avatar benschulz avatar buster avatar chills42 avatar eijebong avatar fabricedesre avatar golddranks avatar hgrecco avatar jlevon avatar ktossell avatar mikedilger avatar niax avatar paolobarbolini avatar quininer avatar sno2 avatar thommay avatar untitaker avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

rust-email's Issues

Breaks under nightly

The FromStr trait has changed so much that rust-email's impl breaks. This is probably a good time to fix #7 too.

FromStr for Mailbox has surprising behaviour

FromStr parses the whole string into the address field. But if I have a from field like "Pyry Kontio [email protected]", I'd expect it parse the first part into the name field and the part inside the <> into the address field.

If it seems hard to break current functionality, Mailbox would should at least provide another method for attempting to parse this. This surprising behaviour breaks some downstream crates too โ€“ I came here because I got noticed this behaviour on Lettre.

Review usage of unstable APIs

Rust's nightly as of 2015-01-09 has warnings for usage of unstable APIs on by default - showing up APIs that may be going away shortly. It'd be nice to be ahead of the curve for a change. See the build log for 0.0.7 for a full list.

  • as_slice, slice, slice_from, slice_to usages should use slicing syntax or other
  • std::fmt::Show/std::fmt::String is still unstable - awaiting outcome from upstream
  • Range notation instead of range

fail on lines over 998 characters

My simple test looks like this:

    #[test]
    fn test_long_lines() {
        let mail_str = "From:iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\r\n\r\n\r\n";
        let mime_msg = MimeMessage::parse(mail_str);
        // assert!(mime_msg.is_err()); shouldn't the parser fail here with some sort of error?
        let from_head: ParsingResult<String> = mime_msg.unwrap().headers.get_value("From".to_owned());
        assert!(from_head.is_err());
    }

Shouldn't MimeMessage::parse() return some kind of Error, stating that the line was too long or did i misread the RFC? According to https://tools.ietf.org/html/rfc5322#section-2.1.1 every line MUST be smaller then 998". Clearly my mail_str is not RFC compliant, but when receiving mails i can't rely on the comformance of the mail to the RFC.

Review usage of unwrap and panics

While removing usages of unstable features, I've put quite a lot of unwraps in the code. I don't think the code now panics more on bad input than it did before (since the unstable APIs paniced themselves), but still.

Reading headers without the rest of the message

I'm experimenting with rust-email for an e-mail client project.

I need to read the headers from many messages (ie a mailbox), without having to read in and parse the entire (possibly huge) e-mail bodies, to display a message index.

The best option I can see so far is to manually read chunks from each message and scan myself until I can see a double line break, then feed that data into an Rfc5322 and call consume_header() repeatedly. Which is fine, but it's a shame to have to duplicate a small part of the parsing. It'd be nice for me if the the parser could work from a std::io::Read or std::io::BufRead, say, and so take either a file or string. (Acknowledging that UTF-8 handling needs doing somewhere!)

I'd be interested in suggestions of better ways to do it, or changes/additions to this crate which might happen in future.

Support for Unix line endings?

While the RFCs clearly specify CRLF endings in emails/MIME boundaries, it turns out that e-mails are normally written to disk by the MTA with just LF on Linux/Unix systems.
I would therefore find it handy to have an LF option, or simply to allow both. It would be a shame to have to convert LFs back to CRLF before feeding to MimeMessage, especially with large messages. :-)

Header lookup should be case insensitive

I think HeaderMap::get should be case insensitive, eg headers.get("Content-Transfer-Encoding") should still work if the actual header is spelled "Content-transfer-encoding". I guess I would go for ordered_headers having the original case and the headers HashMap storing lower-cased keys (translating whenever it's used).

Final MIME boundary not handled

MIME messages with final 'encapsulation' boundary (ending in --) parse incorrectly. The last boundary is included as part of the last MIME part.
If this is indeed an issue (and not me missing something), I'll be happy to fix it.

the trait `core::marker::Sized` is not implemented for the type `Self`

Just as a heads up, it looks like rust-email will stop working in rust 1.5:

/email-0.0.12/src/header.rs:24:5: 24:58 warning: the trait `core::marker::Sized` is not implemented for the type `Self` [E0277]
/email-0.0.12/src/header.rs:24     fn from_header(value: String) -> ParsingResult<Self>;
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/email-0.0.12/src/header.rs:24:5: 24:58 help: run `rustc --explain E0277` to see a detailed explanation
/email-0.0.12/src/header.rs:24:5: 24:58 note: `Self` does not have a constant size known at compile-time
/email-0.0.12/src/header.rs:24:5: 24:58 note: this warning results from recent bug fixes and clarifications; it will become a HARD ERROR in the next release. See RFC 1214 for details.
/email-0.0.12/src/header.rs:24     fn from_header(value: String) -> ParsingResult<Self>;
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/email-0.0.12/src/header.rs:24:5: 24:58 note: required by `core::result::Result`

as_string() produces empty line in header that can cause MTA rejection

Under some circumstances a the header in the final email contains an empty line. We are building an email client, and some messages are rejected because of this: deltachat/deltachat-core-rust#2118

This test reproduces the problem:

#[test]
fn test_no_empty_directly() {
    let to_tuples = vec![
        ("Nnnn", "[email protected]"),
        ("๐Ÿ˜€ ttttttt", "[email protected]"),
        ("dididididididi", "[email protected]"),
        ("Ttttttt", "[email protected]"),
        ("Mmmmm", "[email protected]"),
        ("Zzzzzz", "[email protected]"),
        ("Xyz", "[email protected]"),
        ("", "[email protected]"),
        ("qqqqqq", "[email protected]"),
        ("bbbb", "[email protected]"),
        ("", "[email protected]"),
        ("rqrqrqrqr", "[email protected]"),
        ("tttttttt", "[email protected]"),
        ("", "[email protected]"),
    ];
    let mut to = Vec::new();
    for (name, addr) in to_tuples {
        if name.is_empty() {
            to.push(Address::new_mailbox(addr.to_string()));
        } else {
            to.push(Address::new_mailbox_with_name(
                name.to_string(),
                addr.to_string(),
            ));
        }
    }

    let mut message = email::MimeMessage::new_blank_message();
    message.headers.insert(
        (
            "Content-Type".to_string(),
            "text/plain; charset=utf-8; format=flowed; delsp=no".to_string(),
        )
            .into(),
    );
    message
        .headers
        .insert(Header::new_with_value("To".into(), to).unwrap());
    message.body = "Hi".to_string();

    println!("======= HEADERS BEFORE CALL TO AS_STRING: =======");
    for h in message.headers.iter() {
        println!("{}", h);
    }
    let msg = message.as_string(); // <-- seems like here the empty line is introduced

    let header_end = msg.find("Hi").unwrap();
    let headers = msg[0..header_end].trim();
    println!(
        "======= HEADERS AFTER CALL TO AS_STRING: =======\n{}\n",
        headers
    );
    assert!(!headers.lines().any(|l| l.trim().is_empty())); // <--  panics
}

Output:

======= HEADERS BEFORE CALL TO AS_STRING: =======
Content-Type: text/plain; charset=utf-8; format=flowed; delsp=no
To: Nnnn <[email protected]>, 
        =?utf-8?q?=F0=9F=98=80_ttttttt?= <[email protected]>, 
        dididididididi <[email protected]>, Ttttttt <[email protected]>, 
        Mmmmm <[email protected]>, Zzzzzz <[email protected]>, 
        Xyz <[email protected]>, <[email protected]>, qqqqqq <[email protected]>, 
        bbbb <[email protected]>, <[email protected]>, rqrqrqrqr <[email protected]>, 
        tttttttt <[email protected]>, <[email protected]>
======= HEADERS AFTER CALL TO AS_STRING: =======
Content-Type: text/plain; charset=utf-8; format=flowed; delsp=no
To: Nnnn <[email protected]>, 
        =?utf-8?q?=F0=9F=98=80_ttttttt?= <[email protected]>, 
        dididididididi <[email protected]>, Ttttttt <[email protected]>, 
        Mmmmm <[email protected]>, Zzzzzz <[email protected]>, 
        Xyz <[email protected]>, <[email protected]>, qqqqqq <[email protected]>, 
        bbbb <[email protected]>, <[email protected]>, rqrqrqrqr <[email protected]>,

        tttttttt <[email protected]>, <[email protected]>

thread 'mimefactory::tests::test_no_empty_directly' panicked at 'assertion failed: !headers.lines().any(|l| l.trim().is_empty())', src/mimefactory.rs:1649:9

Change Rc โ†’ Arc

Rc prevents the datatypes defined in this crate from being Send. This affects some downstream crates that use the data types in this crate for implementing email-related stuff. Sometimes these things need to be send between threads (for example, when you have one mailer thread and you prepare emails in many threads and send them to the mailer thread), so this hinders the usability of the types defined here.

Infinite loop with em-dash in header

I've received an e-mail with a (UTF-8) em dash in the subject header, which causes consume_unstructured() to loop forever. A nearly minimal example which triggers the issue (tested using the parse_email example):

00000000 53 75 62 6a 65 63 74 3a 20 e2 80 94 20 61 6c 6c |Subject: ... all|
00000010 0a |.|

The m-dash fails the is_vchar() test so the consume_while() doesn't make any progress.

Support RFC2047 encoding on Header's to_string

Headers should (as required) use RFC2047 encoding when being coerced into a string for inclusion in a MimeMessage.

It should:

  • Support determination of charset encoding as determined by the user, but default to UTF-8
  • Decide automagically if it should use Q encoding or BASE64, based on whichever is shorter
  • Play nicely with header folding (Perhaps ToFoldedHeader should have a requirement to have handled encoding yourself)
  • Not need to do any special manipulation to strings that are already 7-bit ASCII.

Relicense under dual MIT/Apache-2.0

This issue was automatically generated. Feel free to close without ceremony if
you do not agree with re-licensing or if it is not possible for other reasons.
Respond to @cmr with any questions or concerns, or pop over to
#rust-offtopic on IRC to discuss.

You're receiving this because someone (perhaps the project maintainer)
published a crates.io package with the license as "MIT" xor "Apache-2.0" and
the repository field pointing here.

TL;DR the Rust ecosystem is largely Apache-2.0. Being available under that
license is good for interoperation. The MIT license as an add-on can be nice
for GPLv2 projects to use your code.

Why?

The MIT license requires reproducing countless copies of the same copyright
header with different names in the copyright field, for every MIT library in
use. The Apache license does not have this drawback. However, this is not the
primary motivation for me creating these issues. The Apache license also has
protections from patent trolls and an explicit contribution licensing clause.
However, the Apache license is incompatible with GPLv2. This is why Rust is
dual-licensed as MIT/Apache (the "primary" license being Apache, MIT only for
GPLv2 compat), and doing so would be wise for this project. This also makes
this crate suitable for inclusion and unrestricted sharing in the Rust
standard distribution and other projects using dual MIT/Apache, such as my
personal ulterior motive, the Robigalia project.

Some ask, "Does this really apply to binary redistributions? Does MIT really
require reproducing the whole thing?" I'm not a lawyer, and I can't give legal
advice, but some Google Android apps include open source attributions using
this interpretation. Others also agree with
it
.
But, again, the copyright notice redistribution is not the primary motivation
for the dual-licensing. It's stronger protections to licensees and better
interoperation with the wider Rust ecosystem.

How?

To do this, get explicit approval from each contributor of copyrightable work
(as not all contributions qualify for copyright, due to not being a "creative
work", e.g. a typo fix) and then add the following to your README:

## License

Licensed under either of

 * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
 * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)

at your option.

### Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
additional terms or conditions.

and in your license headers, if you have them, use the following boilerplate
(based on that used in Rust):

// Copyright 2016 rust-email Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

It's commonly asked whether license headers are required. I'm not comfortable
making an official recommendation either way, but the Apache license
recommends it in their appendix on how to use the license.

Be sure to add the relevant LICENSE-{MIT,APACHE} files. You can copy these
from the Rust repo for a plain-text
version.

And don't forget to update the license metadata in your Cargo.toml to:

license = "MIT OR Apache-2.0"

I'll be going through projects which agree to be relicensed and have approval
by the necessary contributors and doing this changes, so feel free to leave
the heavy lifting to me!

Contributor checkoff

To agree to relicensing, comment with :

I license past and future contributions under the dual MIT/Apache-2.0 license, allowing licensees to chose either at their option.

Or, if you're a contributor, you can check the box in this repo next to your
name. My scripts will pick this exact phrase up and check your checkbox, but
I'll come through and manually review this issue later as well.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.