Coder Social home page Coder Social logo

mail-builder's People

Contributors

danielorihuela avatar mdecimus avatar mucinoab 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

mail-builder's Issues

[Request] New version

Hello @mdecimus.

First of all thank you for your work on this library.

I was trying to use this lib at the 0.1.2 version but i found too the bug you fixed here. Do you think that a new version of this lib could be available soon?

Thank you in advance.

binary_inline should generate a multipart/related container

Hi! I think this might be two bugs, one here with generation and one in mail-parser in understanding the result.

When using binary_inline to define an inline attachment, the html part and the attachment that is being referenced should belong in the same multipart/related container in order to be referenced correctly. https://stackoverflow.com/a/30424938/149111 has some practical examples.

That container is missing from the built message.

In addition, when parsing the result back with the mail-parser crate, it believes that there are multiple text and html parts.

You can see this if you modify one of the existing test cases:

diff --git a/src/lib.rs b/src/lib.rs
index a7a93e2..eaa9a45 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -613,6 +613,7 @@ mod tests {
             )
             .write_to_vec()
             .unwrap();
-        Message::parse(&output).unwrap();
+        let parsed = Message::parse(&output).unwrap();
+        panic!("{:#?}", parsed);
     }
 }

the top of the struct shows multiple parts for text and html:

---- tests::build_message stdout ----
thread 'tests::build_message' panicked at 'Message {
    html_body: [
        3,
        4,
    ],
    text_body: [
        2,
        4,
    ],
    attachments: [
        4,
        5,
        6,
    ],
    parts: [

it's interesting to see that both the html and text body list 4 as an additional part, which is also listed under attachments; I think that is probably the binary_inline part; it's the first attachment defined in the test and shows up first in the attachments array.

Custom Content-Transfer-Encoding leads to duplicated header

Let's say I have a MimePart. If I do sth like:

part.header("Content-Transfer-Encoding", Raw::new("8bit"));

then the final generated MIME message contains twice the Content-Transfer-Encoding header. What could be the best way to solve this matter?

Incorrect new lines in the header

I'm parsing an email with mail-parse and building a new mail that has truncated body content. What I would like to todo is reuse original headers.

========================================
Return-Path: Text("[email protected]")
Delivered-To: Text("[email protected]")
Received: Text("from 139-162-244-188.cprapid.com\n\tby 139-162-244-188.cprapid.com with LMTP\n\tid RQb5Ojfdd2O5LikAqCNTnA\n\t(envelope-from <[email protected]>)\n\tfor <[email protected]>; Fri, 18 Nov 2022 19:29:59 +0000")
Return-Path: Text("[email protected]")
Envelope-to: Text("[email protected]")
Delivery-date: Text("Fri, 18 Nov 2022 19:30:00 +0000")
Received: Text("from pajkovsky by 139-162-244-188.cprapid.com with local (Exim 4.95)\n\t(envelope-from <[email protected]>)\n\tid 1ov8pO-00A1jF-Dg\n\tfor [email protected];\n\tWed, 16 Nov 2022 03:11:06 +0000")
To: Address(Addr { name: None, address: Some("[email protected]") })
Subject: Text("[My Company] Your site has updated to WordPress 6.1.1")
X-PHP-Script: Text("cpanel.pajkovsky.io/wp-cron.php for 139.162.244.188\n X-PHP-Originating-Script: 1001:PHPMailer.php")
Date: DateTime(DateTime { year: 2022, month: 11, day: 16, hour: 3, minute: 11, second: 6, tz_before_gmt: false, tz_hour: 0, tz_minute: 0 })
From: Address(Addr { name: Some("WordPress"), address: Some("[email protected]") })
Message-ID: Text("[email protected]")
X-Mailer: Text("PHPMailer 6.6.5 (https://github.com/PHPMailer/PHPMailer)")
MIME-Version: Text("1.0")
Content-Type: ContentType(ContentType { c_type: "text", c_subtype: Some("plain"), attributes: Some([("charset", "UTF-8")]) })
[src/main.rs:33] &v = "from 139-162-244-188.cprapid.com\n\tby 139-162-244-188.cprapid.com with LMTP\n\tid RQb5Ojfdd2O5LikAqCNTnA\n\t(envelope-from <[email protected]>)\n\tfor <[email protected]>; Fri, 18 Nov 2022 19:29:59 +0000"
[src/main.rs:33] &v = "from pajkovsky by 139-162-244-188.cprapid.com with local (Exim 4.95)\n\t(envelope-from <[email protected]>)\n\tid 1ov8pO-00A1jF-Dg\n\tfor [email protected];\n\tWed, 16 Nov 2022 03:11:06 +0000"
========================================
Return-Path: [email protected]
Delivered-To: [email protected]
Received: from 139-162-244-188.cprapid.com
        by 139-162-244-188.cprapid.com with
         LMTP
        id RQb5Ojfdd2O5LikAqCNTnA
        (envelope-from <[email protected]>)

        for <[email protected]>; Fri, 18 Nov 2022 19:29:59 +0000
Return-Path: [email protected]
Envelope-to: [email protected]
Delivery-date: Fri, 18 Nov 2022 19:30:00 +0000
Received: from pajkovsky by 139-162-244-188.cprapid.com with local (Exim 4.95)

        (envelope-from <[email protected]>)
        id 1ov8pO-00A1jF-Dg

        for [email protected];
        Wed, 16 Nov 2022 03:11:06 +0000
To: <[email protected]>

But I'm seeing Received has an unexpected new line in the header. I am not convinced that's correct.

`BodyPart::Binary` and `BodyPart::Text` ignores existing `Content-Transfer-Encoding` header

let builder = MessageBuilder::new()
    .body(MimePart { 
        headers: vec![
            (
                Cow::Borrowed("Content-Transfer-Encoding"), Text {
                    text: Cow::Borrowed("7bit") 
                }.into()
            )
        ], 
        contents: BodyPart::Binary(Cow::Borrowed(b"Hello"))
    });
println!("{}", builder.write_to_string()?);

The above code produces:

Message-ID: <175a1d6d39c6b774.dd9fc513b5d45e31.fed9a95d3f7174ad@FA-0455>
Date: Fri, 28 Apr 2023 13:49:25 +0000
Content-Transfer-Encoding: 7bit
Content-Transfer-Encoding: base64

SGVsbG8=

Note that the "Content-Transfer-Encoding" header has been duplicated. Also note that the content has been encoded in base64, and there is no way to encode it in anything other than base64, when using non text content types.

I would expect it to produce:

Message-ID: <175a1d6d39c6b774.dd9fc513b5d45e31.fed9a95d3f7174ad@FA-0455>
Date: Fri, 28 Apr 2023 13:49:25 +0000
Content-Transfer-Encoding: 7bit

Hello

The same issue (but reversed) occurs when using BodyPart::Text

Add ability to customize the Content-Transfer-Encoding header

When creating encrypted multipart, the 2 inner parts application/pgp-encrypted and application/octet-stream should not contain anything else. From the RFC:

The multipart/encrypted MIME body MUST consist of exactly two body
parts, the first with content type "application/pgp-encrypted". This
body contains the control information. A message complying with this
standard MUST contain a "Version: 1" field in this body. Since the
OpenPGP packet format contains all other information necessary for
decrypting, no other information is required here.

The second MIME body part MUST contain the actual encrypted data. It
MUST be labeled with a content type of "application/octet-stream".

The first inner part that should contain Version: 1 ends up being base64 encoded:

Content-Type: application/pgp-encrypted
Content-Transfer-Encoding: base64

VmVyc2lvbjogMQ==

Instead of:

Content-Type: application/pgp-encrypted

Version: 1

I guess adding a condition on encrypted (and signed) parts could be enough. Or adding the ability to override (or remove) the header.

Support for multipart/signed & multipart/encrypted

I am working on a PGP compliant email application using this library and I've noticed however that adding a content_type to the headers of a message_builder such that

message_builder.header("Content-Type", "multipart/encrypted; protocol=\"application/pgp-encrypted\"")
(See https://datatracker.ietf.org/doc/html/rfc3156#section-4)
Doesn't do anything, that is because when the message_builder gets transformed into a string via write the function fn write_to(self, mut output: impl Write) -> io::Result<()> which after adding date and message-id fields, will proceed to. call fn write_body(self, output: impl Write) -> io::Result<()> which, before writing does set the Content-Type depending on the contents, which becomes an issue as for PGP messages it is required to have the correct multipart (see https://datatracker.ietf.org/doc/html/rfc3156#section-4 & https://datatracker.ietf.org/doc/html/rfc1847#section-2).

I however, see that Stalwartlabs has a PGP compliant email application (see https://stalw.art/) so maybe I am misusing the library and this is a non-issue. If not, and mail-builder indeed does not handle custom content-types, could it be possible to make a PR for it with a possible solution or the project isn't open to them?

Apologies if this isn't the proper way to ask this sort of questions/issues, it is my first time working with open source projects.

Addition of BodyPart::Raw

I'd like to be able to write a custom encoding type, as allowed for by RFC 2045 p.15.

This body type would operate exactly like BodyType::Text/Binary, but not add any Content-Transfer-Encoding headers, and directly write a raw [u8] to the output.

MIME-Version Header Field missing

RFC-2045 Section 4 specifies that the MIME-version header is mandatory.
The resulting header for MIME messages that comply with RFC-2045 is MIME-Version: 1.0.

This header is not set by the library. I checked it running the example code

// Build a simple text message with a single attachment
let eml = MessageBuilder::new()
    .from(("John Doe", "[email protected]"))
    .to("[email protected]")
    .subject("Hello, world!")
    .text_body("Message contents go here.")
    .attachment("image/png", "image.png", [1, 2, 3, 4].as_ref())
    .write_to_string()
    .unwrap();
    
// Print raw message
println!("{}", eml);

This returns

From: "John Doe" <[email protected]>
To: <[email protected]>
Subject: Hello, world!
Message-ID: <17d43931df08db90.6b7491d8ba5bee6f.ee4d742b44dcad73@Daniels-MacBook-Air.local>
Date: Thu, 30 May 2024 09:10:44 +0000
Content-Type: multipart/mixed; 
        boundary="17d43931df0921e0_9ac0b9239a66a84_ee4d742b44dcad73"


--17d43931df0921e0_9ac0b9239a66a84_ee4d742b44dcad73
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit

Message contents go here.
--17d43931df0921e0_9ac0b9239a66a84_ee4d742b44dcad73
Content-Type: image/png
Content-Disposition: attachment; filename="image.png"
Content-Transfer-Encoding: base64

AQIDBA==

--17d43931df0921e0_9ac0b9239a66a84_ee4d742b44dcad73--

@mdecimus are you open to reviewing and merging a PR?

Build email from parsed email

Is there a convenient way to use this crate in conjunction with your other crate (mail-parser) to

  1. read in an email,
  2. convert the Message to a MessageBuilder,
  3. make some modifications to the email
  4. then send it (using mail-send or, in my case, a third party library)

Current best solution I have is to copy over field by field. I'm hoping there's a built in way.... '

The use case for this is I'm building a marketing engine. The user sends an email to my app, the app reads the email and adds unsubscribe links, edits content data, etc.

Sending email - how?

Hi,
could you give example of what smtp client is the best for your lib to sending email?

Multipart message has double line break after header

When building a multipart message, I receive two line breaks after the header. Possibly related, there are also two line breaks at the end of the message.

Here is what the output looks like:

Message-ID: <175a169b74fdbff2.dd9fc513b5d45e31.fed9a95d3f7174ad@FA-0455>
Date: Fri, 28 Apr 2023 11:44:27 +0000
Content-Type: multipart/mixed; 
	boundary="175a169b74fe1006_7bd73ecd351eda46_fed9a95d3f7174ad"


--175a169b74fe1006_7bd73ecd351eda46_fed9a95d3f7174ad
Content-Transfer-Encoding: 7bit

Hello
--175a169b74fe1006_7bd73ecd351eda46_fed9a95d3f7174ad


This is the code to build the above message:

let builder = MessageBuilder::new()
  .body(MimePart { 
      contents: BodyPart::Multipart(vec![
          MimePart { 
              contents: BodyPart::Text(Cow::Borrowed("Hello")), 
              headers: vec![] }
      ]), 
      headers: vec![]
  });

println!("{}", builder.write_to_string()?);

support format=flowed?

  1. I'm not sure whether this library should assume that a trailing space means that it should use quoted-printable instead of utf-7 -- what's the reasoning behind this?
  2. It would be nice to have a way to set format=flowed -- I put together some commits on https://github.com/alexwennerberg/mail-builder but I'm not sure if it's the best way to do it or something you want to support in this library

Binary `text/plain` attachment considered as `PartType::Text` instead of `PartType::Binary`

Given the following builder:

let msg = MessageBuilder::new()
    .from("from@localhost")
    .to("to@localhost")
    .subject("subject")
    .text_body("Hello, world!")
    .binary_attachment("text/plain", "attachment.txt", "Hello, world!".as_bytes())
    .write_to_string()
    .unwrap();

Which compiles to:

From: <from@localhost>
To: <to@localhost>
Subject: subject
Message-ID: <176218bdb01133ec.2d80ee539da5279a.52ee893e4d3a9db2@soywod>
Date: Wed, 24 May 2023 13:53:33 +0000
Content-Type: multipart/mixed; 
	boundary="176218bdb01183df_cbb8680d1cefa3af_52ee893e4d3a9db2"


--176218bdb01183df_cbb8680d1cefa3af_52ee893e4d3a9db2
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit

Hello, world!
--176218bdb01183df_cbb8680d1cefa3af_52ee893e4d3a9db2
Content-Type: text/plain
Content-Disposition: attachment; filename="attachment.txt"
Content-Transfer-Encoding: 7bit

Hello, world!
--176218bdb01183df_cbb8680d1cefa3af_52ee893e4d3a9db2--

If I parse back this email with mail-parser, the body of the attachment is considered a PartType::Text. In my opinion it should be a PartType::Binary as it was intended with the builder.

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.