Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inline Attachments + Transactional Templates = broken email #1404

Open
thexeos opened this issue Jun 26, 2024 · 1 comment
Open

Inline Attachments + Transactional Templates = broken email #1404

thexeos opened this issue Jun 26, 2024 · 1 comment

Comments

@thexeos
Copy link

thexeos commented Jun 26, 2024

Use case

Sending a transactional email (saved as Dynamic Template in SendGrid) with inlined images (to avoid remote images getting blocked by default on virtually 100% of modern email clients), such as header design, product images, logo in the footer.

Issue

When passing attachments and templateId in one call, the structure of the generated email is spec non-conforming and results in broken email with inline images showing as separate attachments.

sgMail.send({
  to: '[email protected]',
  from: '[email protected]',
  subject: 'Hello world',
  text: 'Hello plain world!',
  html: '<p>Hello HTML world! <img src="cid:img2" /></p>',
  templateId: 'd-f43daeeaef504760851f727007e0b5d0',
  dynamic_template_data: {
    subject: 'Testing Templates & Stuff',
    name: 'Some "Testing" One',
    city: '<b>Denver<b>',
  },
  attachments: [
    {
      content: textBuffered.toString('base64'),
      filename: 'img1.jpg',
      type: 'image/jpeg',
      disposition: 'inline',
      content_id: 'img1',
    },
    {
      content: textBuffered.toString('base64'),
      filename: 'img2.jpg',
      type: 'image/jpeg',
      disposition: 'inline',
      content_id: 'img2',
    },
  ],
})

Expected structure

multipart/alternative
├── text/plain
└── multipart/related
    ├── text/html
    ├── image/jpeg (inline image 1)
    └── image/jpeg (inline image 2)

Actual structure

multipart/related
└── multipart/alternative
    ├── text/plain
    └── text/html
├── image/jpeg (inline image 1)
└── image/jpeg (inline image 2)

Known workarounds

  • Storing email HTML/Text in your application codebase and passing them together with attachments to API for every email
  • Doing the same as above, plus formatting the email for SMTP delivery and using SendGrid SMTP to send your email
  • Sending emails from your own MTA

Additional comments

Since Transactional Templates don't support inline image attachments (for some reason) it's already inconvenient enough for developers that inline images must be passed via an API parameters. Now with this issue, Transactional Templates completely lose value and it puts developers one step away from constructing their own email and using "pure MTA" service instead.

@Justin-Terry
Copy link

Justin-Terry commented Nov 25, 2024

I also hit this issue and having it not work was not an option. I dug in and found the bug. This patch will fix the problem. It's a pretty straight forward issue, what should be content_id in the request JSON is being sent as contentId.

@sendgrid+helpers+8.0.0.patch

If you don't want to download the file, here's the contents of @sendgrid+helpers+8.0.0.patch

 if (!attachments.every(attachment => !attachment.disposition || typeof attachment.disposition === 'string')) {
        throw new Error('Expected the attachment\'s `disposition` field to be a string');
      }
      this.attachments = attachments;
      this.attachments = attachments.map((attachment) => ({
        ...attachment,
        content_id: attachment.contentId,
      }));
    }
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants