Gửi một email
`emails.send`: một thư, gửi ngay hoặc gửi sau.
emails.send
const email = await openemail.emails.send({ from: { email: '[email protected]', name: 'Acme Billing' }, to: ['[email protected]', 'Grace <[email protected]>'], cc: '[email protected]', bcc: [{ email: '[email protected]' }], replyTo: '[email protected]', subject: 'Your September invoice', html: '<p>Invoice attached.</p>', text: 'Invoice attached.', headers: { 'X-Campaign': 'invoices' }, attachments: [{ filename: 'invoice.pdf', content: pdfBytes }], threadId: 'thread_…', scheduledAt: 'PT1H', tags: { order: '4021' }, tracking: { opens: true, clicks: true },})to, cc và bcc nhận một hoặc nhiều người nhận, và một người nhận đơn lẻ sẽ được tự động bọc thành mảng. Mỗi người nhận có thể là địa chỉ trần, Name <addr@host>, hoặc { email, name }.
Tham số
fromRecipientInputbắt buộc- Người gửi. Địa chỉ trần, `Name <addr@host>`, hoặc một object. Phải là địa chỉ mà key này được phép gửi. Không có người gửi dự phòng, vì dự phòng sẽ là địa chỉ mặc định của không gian làm việc, thứ vốn thay đổi khi địa chỉ được thêm hoặc gỡ.
toRecipientInput | RecipientInput[]bắt buộc- Một hoặc nhiều người nhận; người nhận đơn lẻ sẽ được tự động bọc thành mảng. Tối đa 50 địa chỉ gộp chung to, cc và bcc.
ccRecipientInput | RecipientInput[]- Tính vào giới hạn 50 người nhận.
bccRecipientInput | RecipientInput[]- Không bao giờ xuất hiện trong nội dung mà người khác nhận được, vì mỗi người nhận được gửi một phong bì riêng.
replyToRecipientInput- Một địa chỉ duy nhất, được gửi dưới dạng header Reply-To.
subjectstring- Tối đa 998 ký tự, giới hạn độ dài dòng của RFC 5322. Mặc định là rỗng.
htmlstring- Bắt buộc có một trong html, text, draftId hoặc template. HTML là phần người nhận thấy khi có cả html và text.
textstring- Phần văn bản thuần.
template{ id, version?, props?, slots? }- Render một template đã lưu ở phía máy chủ. `version` dùng để ghim phiên bản; bỏ trống để dùng bản đang được xuất bản khi request được chấp nhận. Prop không xác định hoặc bị thiếu sẽ trả về 422 thay vì để trống trong thư.
draftIdstring- Gửi một bản nháp đã lưu với phong bì này.
headersRecord<string, string>- `X-*`, `List-*`, Reply-To, Precedence, Auto-Submitted, Importance, Priority và Feedback-Id. Mọi header do tầng truyền tải tự đặt đều bị từ chối thay vì bị âm thầm bỏ qua.
attachmentsAttachmentInput[]- `{ filename, content, contentType? }`, hoặc `{ fileId }` trỏ tới tệp đã có trong workspace. Truyền byte cho content và chúng sẽ được tự động mã hóa base64. Tối đa 20 tệp, với tổng dung lượng tệp nhúng 5 MB sau khi giải mã. Tệp đã lưu có thể lớn hơn và được gửi dưới dạng liên kết tải xuống.
attachmentDeliveryAttachmentDeliveryMode- `mime`, `link` hoặc `auto`. `auto` gửi tệp dưới dạng liên kết tải xuống khi chúng vượt quá 2 MB trên domain có tên miền files đang hoạt động, còn lại thì gửi kèm trong thư. Nếu bỏ trống, cài đặt của hộp thư được áp dụng, mặc định là `auto`.
threadIdstring- Trả lời vào một luồng có sẵn. Tầng truyền tải tạo In-Reply-To và References.
scheduledAtDate | string- Một Date, một thời điểm ISO-8601, hoặc một khoảng thời gian như `PT1H`. Tối đa một năm tới, không bao giờ ở quá khứ. Không thể kết hợp với cancellableForSeconds.
cancellableForSecondsnumber- 0 đến 900. Cửa sổ hoàn tác cho lần gửi ngay: cơ chế hoàn tác của trình soạn thư, được cung cấp ra ngoài thay vì cố định trong code.
tagsRecord<string, string>- Tối đa 10 nhãn, được trả về nguyên và có thể lọc. Không bao giờ được diễn giải.
signatureboolean- Thư này có kèm chữ ký của địa chỉ gửi hay không, tức chữ ký riêng của địa chỉ đó hoặc nếu không có thì chữ ký đặt cho All addresses. Mặc định là true, vì chữ ký thuộc về địa chỉ chứ không thuộc về client đã gửi thư. Hãy đặt `false` cho thư mà một chương trình gửi thay mặt ai đó, chẳng hạn biên nhận, thư đặt lại mật khẩu hay bản tin tổng hợp, những loại thư không cần lời ký tên của một người ở cuối.
tracking{ opens?, clicks? }- Có thêm pixel theo dõi lượt mở và viết lại liên kết cho thư này hay không. Bật trừ khi chủ workspace đã tắt theo dõi cho địa chỉ gửi hoặc cho All addresses, và bất kỳ trường nào được nêu ở đây sẽ quyết định cho riêng thư đó bất kể cài đặt của địa chỉ.
translate{ to, from?, subject?, includeOriginal? }- Gửi thư bằng ngôn ngữ của người nhận. `to` nhận mã ngôn ngữ, tên tiếng Anh hoặc tên bản địa của ngôn ngữ; `subject` và `includeOriginal` đều mặc định là true. Được phân giải khi request được chấp nhận, nên thư hẹn giờ mang đúng nội dung đã được duyệt. Bị từ chối nếu đi cùng `draftId`.
Phản hồi
idstring- Id của lần gửi, `msg_…`. Dùng nó cho `get`, `cancel`, `reschedule` và `getTracking`.
statusEmailStatus- queued, scheduled, sending, sent, partial, cancelled hoặc failed. Hãy đọc trường này thay vì dựa vào việc promise đã phân giải. `partial` là trạng thái riêng: một số người nhận đã nhận thư và không thể thu hồi, nên thử lại là sai và báo thất bại là không đúng sự thật.
mode'live' | 'test'- Loại khoá nào đã gửi nó. Một lần gửi thử nghiệm được ghi lại và không bao giờ được truyền đi.
fromstring- Địa chỉ thực sự được cấp quyền và đưa lên đường truyền, vốn không phải lúc nào cũng là địa chỉ đã yêu cầu.
subjectstring | null- Đúng như đã gửi.
messageIdstring | null- Message-ID theo RFC 5322. Null cho đến khi phần MIME tồn tại. Dịch vụ gửi sẽ viết lại header này trên đường ra, nên không một bounce hay báo cáo gửi nào mang giá trị này. `id` mới là thứ mà một sự kiện quay về theo.
threadIdstring | null- Luồng thư mà nó rơi vào.
transportstring | null- Cách thông điệp rời đi. Null cho đến khi được điều phối.
attemptsnumber- Đã thử điều phối bao nhiêu lần.
lastErrorstring | null- Lý do lần thử cuối thất bại, nguyên văn.
scheduledAtstring | null- Thời điểm ISO mà thư sẽ được gửi.
cancellableUntilstring | null- Chừng nào thời điểm hiện tại còn trước mốc này, lệnh hủy vẫn có tác dụng.
sentAtstring | null- Thời điểm ISO mà thư đã được gửi.
tagsRecord<string, string>- Những gì bạn đã gửi, được trả về nguyên vẹn.
sourceEmailSource- composer, api, mcp, ai hoặc queue: bề mặt nào đã yêu cầu. `api` chính là client này.
createdAtstring- Thời điểm ISO khi bản ghi được ghi lại.
replayedboolean- True khi một Idempotency-Key trùng với một lần gửi đã tồn tại. Không có gì mới được gửi đi, và đây là thông điệp gốc.
translationEmailTranslationResource | undefined- Chỉ có mặt trên một thông điệp đã được dịch, và chỉ ở nơi mang theo toàn bộ yêu cầu đã lưu: phản hồi này và `get`. `{ language, languageName, detectedSourceLanguage, subject, includeOriginal }`, toàn bộ là mã chứ không phải các hàng ngôn ngữ. Một hàng trong danh sách không bao giờ có nó, nên việc nó vắng mặt ở đó không nói lên điều gì cả.
Bằng ngôn ngữ của người nhận
translate viết thông điệp bằng ngôn ngữ của người khác trước khi nó được gửi đi. Phần thân, và cả tiêu đề trừ khi bạn tắt điều đó, được dịch ngay khi API chấp nhận yêu cầu, và thứ được tạo ra chính là thứ được gửi đi: một bản dịch không thể tạo ra sẽ khiến lần gửi bị từ chối chứ không đăng nó bằng ngôn ngữ bạn đã viết.
const email = await openemail.emails.send({ from: '[email protected]', to: '[email protected]', subject: 'Your September invoice', html: '<p>Invoice attached. Payment is due on the 14th.</p>', translate: { to: 'de' },}) console.log(email.translation)// { language: 'de', languageName: 'German', detectedSourceLanguage: 'en', subject: true, includeOriginal: true }Không ai đọc nội dung đó trước khi nó được gửi đi. emails.translate là cùng một vòng đi-về nhưng dừng sớm hơn một bước. Hãy đưa nó cho một người xem, để họ sửa, rồi gửi đúng thứ họ đã duyệt mà trong lời gọi hoàn toàn không có translate. Truyền nó lần nữa sẽ dịch lần thứ hai và vứt bỏ mọi chỉnh sửa của họ.
const preview = await openemail.emails.translate({ subject: 'Your September invoice', html: '<p>Invoice attached. Payment is due on the 14th.</p>', to: 'de',}) console.log(preview.language.native, preview.detectedSourceLanguage) const approved = await showToSomebody(preview) await openemail.emails.send({ from: '[email protected]', to: '[email protected]', subject: approved.subject, html: approved.html,})import { LANGUAGES, isRtlLanguage, languageByCode, openemail, resolveLanguage } from '@openemail/sdk' LANGUAGES.length // 200 const current = await openemail.languages.list() resolveLanguage('Deutsch')?.code // 'de'resolveLanguage('zh-TW')?.code // 'zh-Hant'languageByCode('DE')?.native // 'Deutsch'isRtlLanguage('ar') // trueBảng này được đóng gói sẵn, theo đúng thứ tự của bộ chọn, nên một bộ chọn có thể được điền trước cả yêu cầu đầu tiên. languages.list() trả về chính những hàng đó lấy từ đường truyền dưới dạng một mảng thuần, dành cho người gọi muốn danh sách hiện tại thay vì danh sách đi kèm phiên bản này. resolveLanguage nhận một mã, một tên tiếng Anh, một tên bản địa hoặc một bí danh (zh-TW là bí danh của một mã không còn được liệt kê), languageByCode khớp chính xác một mã và không phân biệt hoa thường, và mười sáu hàng trong đó viết từ phải sang trái. Hãy tìm kiếm đồng thời trên native, label và code, hiển thị native trước, và lưu lại mã.
emails.translate không được thử lại tự động. Nó tiêu tốn các lời gọi mô hình và không ghi gì cả, nên không có gì để làm idempotent, và một lần thử lại sau một yêu cầu không được trả lời chỉ khiến bạn mua cùng một câu trả lời hai lần.
- Một ngôn ngữ không phân giải được là một
validation_errortrêntranslate.to, trước khi bất cứ thứ gì được gửi đi. translation_too_longkhi vượt quá 30.000 ký tự,translation_not_configuredkhi bản cài đặt chưa cấu hình AI,translation_failedkhi nhà cung cấp không trả lời. Không trường hợp nào trong số đó gửi thông điệp chưa dịch như một phương án dự phòng.- Hoạt động cùng
template: thứ được dịch là kết quả ĐÃ KẾT XUẤT, nên một phần thân đã lưu phục vụ được mọi ngôn ngữ mà khách hàng của bạn đọc. Một template kết xuất ra cả một tài liệu vẫn giữ nguyên doctype, các khối<style>và các quy tắc@font-facecủa nó: chỉ phần thân được đưa tới mô hình và phần còn lại được đặt lại xung quanh nó.<title>của nó được giữ nguyên, mà dù sao cũng chẳng có gì hiển thị nó. - Một lần thử lại không tốn thêm gì. Bản dịch không nằm trong dấu vân tay idempotency (yêu cầu thì có, kể cả
translate), nên thử lại một lần gửi chưa được trả lời với cùngIdempotency-Keysẽ phát lại thông điệp đã tồn tại thay vì dịch và gửi một thông điệp thứ hai. - Một thông điệp đã dịch đang nằm trong hàng đợi hoặc đã hẹn giờ thì bị đóng băng về mặt câu chữ.
emails.reschedulevẫn dời được nó; muốn đổi nội dung thì phải huỷ và gửi lại.
Tệp đính kèm
content là base64 trên đường truyền. Hãy truyền vào các byte và chúng sẽ được mã hoá giúp bạn.
attachments: [ { filename: 'invoice.pdf', content: pdfBytes, contentType: 'application/pdf' },]toBase64 được export sẵn nếu bạn cần dùng ở nơi khác. Nó xử lý theo từng khối, điều mà btoa(String.fromCharCode(...bytes)) không làm. Cách đó hỏng với bất cứ thứ gì lớn hơn khoảng 100 kB, và nó hỏng với tệp thật chứ không phải tệp bạn đã thử nghiệm.