-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(Email Trigger (IMAP) Node): Handle attachments correctly (#9410)
- Loading branch information
Showing
9 changed files
with
213 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* eslint-disable @typescript-eslint/no-use-before-define */ | ||
import * as qp from 'quoted-printable'; | ||
import * as iconvlite from 'iconv-lite'; | ||
import * as utf8 from 'utf8'; | ||
import * as uuencode from 'uuencode'; | ||
|
||
export abstract class PartData { | ||
constructor(readonly buffer: Buffer) {} | ||
|
||
toString() { | ||
return this.buffer.toString(); | ||
} | ||
|
||
static fromData(data: string, encoding: string, charset?: string): PartData { | ||
if (encoding === 'BASE64') { | ||
return new Base64PartData(data); | ||
} | ||
|
||
if (encoding === 'QUOTED-PRINTABLE') { | ||
return new QuotedPrintablePartData(data, charset); | ||
} | ||
|
||
if (encoding === '7BIT') { | ||
return new SevenBitPartData(data); | ||
} | ||
|
||
if (encoding === '8BIT' || encoding === 'BINARY') { | ||
return new BinaryPartData(data, charset); | ||
} | ||
|
||
if (encoding === 'UUENCODE') { | ||
return new UuencodedPartData(data); | ||
} | ||
|
||
// if it gets here, the encoding is not currently supported | ||
throw new Error('Unknown encoding ' + encoding); | ||
} | ||
} | ||
|
||
export class Base64PartData extends PartData { | ||
constructor(data: string) { | ||
super(Buffer.from(data, 'base64')); | ||
} | ||
} | ||
|
||
export class QuotedPrintablePartData extends PartData { | ||
constructor(data: string, charset?: string) { | ||
const decoded = | ||
charset?.toUpperCase() === 'UTF-8' ? utf8.decode(qp.decode(data)) : qp.decode(data); | ||
super(Buffer.from(decoded)); | ||
} | ||
} | ||
|
||
export class SevenBitPartData extends PartData { | ||
constructor(data: string) { | ||
super(Buffer.from(data)); | ||
} | ||
|
||
toString() { | ||
return this.buffer.toString('ascii'); | ||
} | ||
} | ||
|
||
export class BinaryPartData extends PartData { | ||
constructor( | ||
data: string, | ||
readonly charset: string = 'utf-8', | ||
) { | ||
super(Buffer.from(data)); | ||
} | ||
|
||
toString() { | ||
return iconvlite.decode(this.buffer, this.charset); | ||
} | ||
} | ||
|
||
export class UuencodedPartData extends PartData { | ||
constructor(data: string) { | ||
const parts = data.split('\n'); // remove newline characters | ||
const merged = parts.splice(1, parts.length - 4).join(''); // remove excess lines and join lines with empty string | ||
const decoded = uuencode.decode(merged); | ||
super(decoded); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { | ||
PartData, | ||
Base64PartData, | ||
QuotedPrintablePartData, | ||
SevenBitPartData, | ||
BinaryPartData, | ||
UuencodedPartData, | ||
} from '../src/PartData'; | ||
|
||
describe('PartData', () => { | ||
describe('fromData', () => { | ||
it('should return an instance of Base64PartData when encoding is BASE64', () => { | ||
const result = PartData.fromData('data', 'BASE64'); | ||
expect(result).toBeInstanceOf(Base64PartData); | ||
}); | ||
|
||
it('should return an instance of QuotedPrintablePartData when encoding is QUOTED-PRINTABLE', () => { | ||
const result = PartData.fromData('data', 'QUOTED-PRINTABLE'); | ||
expect(result).toBeInstanceOf(QuotedPrintablePartData); | ||
}); | ||
|
||
it('should return an instance of SevenBitPartData when encoding is 7BIT', () => { | ||
const result = PartData.fromData('data', '7BIT'); | ||
expect(result).toBeInstanceOf(SevenBitPartData); | ||
}); | ||
|
||
it('should return an instance of BinaryPartData when encoding is 8BIT or BINARY', () => { | ||
let result = PartData.fromData('data', '8BIT'); | ||
expect(result).toBeInstanceOf(BinaryPartData); | ||
result = PartData.fromData('data', 'BINARY'); | ||
expect(result).toBeInstanceOf(BinaryPartData); | ||
}); | ||
|
||
it('should return an instance of UuencodedPartData when encoding is UUENCODE', () => { | ||
const result = PartData.fromData('data', 'UUENCODE'); | ||
expect(result).toBeInstanceOf(UuencodedPartData); | ||
}); | ||
|
||
it('should throw an error when encoding is not supported', () => { | ||
expect(() => PartData.fromData('data', 'UNSUPPORTED')).toThrow( | ||
'Unknown encoding UNSUPPORTED', | ||
); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('Base64PartData', () => { | ||
it('should correctly decode base64 data', () => { | ||
const data = Buffer.from('Hello, world!', 'utf-8').toString('base64'); | ||
const partData = new Base64PartData(data); | ||
expect(partData.toString()).toBe('Hello, world!'); | ||
}); | ||
}); | ||
|
||
describe('QuotedPrintablePartData', () => { | ||
it('should correctly decode quoted-printable data', () => { | ||
const data = '=48=65=6C=6C=6F=2C=20=77=6F=72=6C=64=21'; // 'Hello, world!' in quoted-printable | ||
const partData = new QuotedPrintablePartData(data); | ||
expect(partData.toString()).toBe('Hello, world!'); | ||
}); | ||
}); | ||
|
||
describe('SevenBitPartData', () => { | ||
it('should correctly decode 7bit data', () => { | ||
const data = 'Hello, world!'; | ||
const partData = new SevenBitPartData(data); | ||
expect(partData.toString()).toBe('Hello, world!'); | ||
}); | ||
}); | ||
|
||
describe('BinaryPartData', () => { | ||
it('should correctly decode binary data', () => { | ||
const data = Buffer.from('Hello, world!', 'utf-8').toString(); | ||
const partData = new BinaryPartData(data); | ||
expect(partData.toString()).toBe('Hello, world!'); | ||
}); | ||
}); | ||
|
||
describe('UuencodedPartData', () => { | ||
it('should correctly decode uuencoded data', () => { | ||
const data = Buffer.from( | ||
'YmVnaW4gNjQ0IGRhdGEKLTImNUw7JlxMKCc9TzxGUUQoMGBgCmAKZW5kCg==', | ||
'base64', | ||
).toString('binary'); | ||
const partData = new UuencodedPartData(data); | ||
expect(partData.toString()).toBe('Hello, world!'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
diff --git a/index.d.ts b/index.d.ts | ||
index f8f89c567f394a538018bfdf11c28dc15e9c9fdc..f3d1cd426711f1f714744474604bd7e321073983 100644 | ||
--- a/index.d.ts | ||
+++ b/index.d.ts | ||
@@ -1,4 +1,4 @@ | ||
/// <reference types="node"/> | ||
|
||
-export function decode(str: string | Buffer): string; | ||
+export function decode(str: string | Buffer): Buffer; | ||
export function encode(str: string | Buffer): string; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.