|
| 1 | +import asyncio |
| 2 | +import os |
| 3 | + |
| 4 | +import resend |
| 5 | +from resend import EmailsReceiving |
| 6 | + |
| 7 | +if not os.environ["RESEND_API_KEY"]: |
| 8 | + raise EnvironmentError("RESEND_API_KEY is missing") |
| 9 | + |
| 10 | +# Retrieve a single received email by ID |
| 11 | +email_id = "006e2796-ff6a-4436-91ad-0429e600bf8a" |
| 12 | + |
| 13 | + |
| 14 | +async def main() -> None: |
| 15 | + received_email: resend.ReceivedEmail = await resend.Emails.Receiving.get_async( |
| 16 | + email_id=email_id |
| 17 | + ) |
| 18 | + |
| 19 | + print(f"\nRetrieved received email: {received_email['id']}") |
| 20 | + print("\n--- Email Details ---") |
| 21 | + print(f"From: {received_email['from']}") |
| 22 | + print(f"To: {received_email['to']}") |
| 23 | + print(f"Subject: {received_email['subject']}") |
| 24 | + print(f"Created at: {received_email['created_at']}") |
| 25 | + print(f"Object type: {received_email['object']}") |
| 26 | + |
| 27 | + print("\n--- Email Content ---") |
| 28 | + html_content = received_email.get("html") |
| 29 | + if html_content: |
| 30 | + print(f"HTML: {html_content[:100]}...") |
| 31 | + else: |
| 32 | + print("HTML: None") |
| 33 | + |
| 34 | + text_content = received_email.get("text") |
| 35 | + if text_content: |
| 36 | + print(f"Text: {text_content[:100]}...") |
| 37 | + else: |
| 38 | + print("Text: None") |
| 39 | + |
| 40 | + print("\n--- Recipients ---") |
| 41 | + print(f"CC: {received_email.get('cc', [])}") |
| 42 | + print(f"BCC: {received_email.get('bcc', [])}") |
| 43 | + print(f"Reply-To: {received_email.get('reply_to', [])}") |
| 44 | + |
| 45 | + print("\n--- Email MIME Headers ---") |
| 46 | + # received_email["headers"] contains the MIME headers of the inbound email |
| 47 | + # (e.g. X-Mailer, DKIM-Signature). These come from the API response body |
| 48 | + # and are part of the email itself, not the HTTP response. |
| 49 | + if received_email.get("headers"): |
| 50 | + for header_name, header_value in received_email["headers"].items(): |
| 51 | + print(f"{header_name}: {header_value}") |
| 52 | + else: |
| 53 | + print("No email headers") |
| 54 | + |
| 55 | + print("\n--- HTTP Response Headers ---") |
| 56 | + # received_email["http_headers"] contains HTTP-level metadata from the Resend API |
| 57 | + # (e.g. x-request-id, x-ratelimit-remaining). Injected by the SDK, never part |
| 58 | + # of the email content. |
| 59 | + if received_email.get("http_headers"): |
| 60 | + print(f"Rate limit: {received_email['http_headers'].get('ratelimit-limit')}") |
| 61 | + print( |
| 62 | + f"Rate limit remaining: {received_email['http_headers'].get('ratelimit-remaining')}" |
| 63 | + ) |
| 64 | + |
| 65 | + print("\n--- Attachments ---") |
| 66 | + if received_email["attachments"]: |
| 67 | + print(f"Total attachments: {len(received_email['attachments'])}") |
| 68 | + for idx, attachment in enumerate(received_email["attachments"], 1): |
| 69 | + print(f"\nAttachment {idx}:") |
| 70 | + print(f" ID: {attachment['id']}") |
| 71 | + print(f" Filename: {attachment['filename']}") |
| 72 | + print(f" Content Type: {attachment['content_type']}") |
| 73 | + print(f" Content Disposition: {attachment['content_disposition']}") |
| 74 | + if attachment.get("content_id"): |
| 75 | + print(f" Content ID: {attachment['content_id']}") |
| 76 | + if attachment.get("size"): |
| 77 | + print(f" Size: {attachment['size']} bytes") |
| 78 | + else: |
| 79 | + print("No attachments") |
| 80 | + |
| 81 | + print("\n--- Listing All Received Emails ---") |
| 82 | + all_emails: EmailsReceiving.ListResponse = await resend.Emails.Receiving.list_async() |
| 83 | + |
| 84 | + print(f"Total emails in this batch: {len(all_emails['data'])}") |
| 85 | + print(f"Has more emails: {all_emails['has_more']}") |
| 86 | + |
| 87 | + if all_emails["data"]: |
| 88 | + for idx, email in enumerate(all_emails["data"], 1): |
| 89 | + print(f"\nEmail {idx}:") |
| 90 | + print(f" ID: {email['id']}") |
| 91 | + print(f" From: {email['from']}") |
| 92 | + print(f" To: {email['to']}") |
| 93 | + print(f" Subject: {email['subject']}") |
| 94 | + print(f" Created: {email['created_at']}") |
| 95 | + print(f" Attachments: {len(email['attachments'])}") |
| 96 | + |
| 97 | + print("\n--- Listing Received Emails with Pagination ---") |
| 98 | + list_params: EmailsReceiving.ListParams = { |
| 99 | + "limit": 5, |
| 100 | + } |
| 101 | + paginated_emails: EmailsReceiving.ListResponse = ( |
| 102 | + await resend.Emails.Receiving.list_async(params=list_params) |
| 103 | + ) |
| 104 | + |
| 105 | + print(f"Retrieved {len(paginated_emails['data'])} emails (limited to 5)") |
| 106 | + print(f"Has more: {paginated_emails['has_more']}") |
| 107 | + |
| 108 | + if paginated_emails["data"] and paginated_emails["has_more"]: |
| 109 | + last_email_id = paginated_emails["data"][-1]["id"] |
| 110 | + print(f"\n--- Getting Next Page (after {last_email_id}) ---") |
| 111 | + next_page_params: EmailsReceiving.ListParams = { |
| 112 | + "limit": 5, |
| 113 | + "after": last_email_id, |
| 114 | + } |
| 115 | + next_page: EmailsReceiving.ListResponse = ( |
| 116 | + await resend.Emails.Receiving.list_async(params=next_page_params) |
| 117 | + ) |
| 118 | + print(f"Next page has {len(next_page['data'])} emails") |
| 119 | + print(f"Next page has more: {next_page['has_more']}") |
| 120 | + |
| 121 | + print("\n--- Listing All Attachments ---") |
| 122 | + all_attachments: EmailsReceiving.Attachments.ListResponse = ( |
| 123 | + await resend.Emails.Receiving.Attachments.list_async(email_id=email_id) |
| 124 | + ) |
| 125 | + |
| 126 | + print(f"Total attachments: {len(all_attachments['data'])}") |
| 127 | + print(f"Has more: {all_attachments['has_more']}") |
| 128 | + |
| 129 | + if all_attachments["data"]: |
| 130 | + for idx, att in enumerate(all_attachments["data"], 1): |
| 131 | + print(f"\nAttachment {idx}:") |
| 132 | + print(f" ID: {att['id']}") |
| 133 | + print(f" Filename: {att['filename']}") |
| 134 | + print(f" Content Type: {att['content_type']}") |
| 135 | + print(f" Size: {att.get('size', 'N/A')} bytes") |
| 136 | + |
| 137 | + if received_email["attachments"] and len(received_email["attachments"]) > 0: |
| 138 | + first_attachment = received_email["attachments"][0] |
| 139 | + attachment_id = first_attachment["id"] |
| 140 | + |
| 141 | + print(f"\n--- Retrieving Attachment Details: {first_attachment['filename']} ---") |
| 142 | + |
| 143 | + attachment_details: resend.EmailAttachmentDetails = ( |
| 144 | + await resend.Emails.Receiving.Attachments.get_async( |
| 145 | + email_id=email_id, |
| 146 | + attachment_id=attachment_id, |
| 147 | + ) |
| 148 | + ) |
| 149 | + |
| 150 | + print(f"Attachment ID: {attachment_details['id']}") |
| 151 | + print(f"Filename: {attachment_details['filename']}") |
| 152 | + print(f"Content Type: {attachment_details['content_type']}") |
| 153 | + print(f"Content Disposition: {attachment_details['content_disposition']}") |
| 154 | + if attachment_details.get("content_id"): |
| 155 | + print(f" Content ID: {attachment_details['content_id']}") |
| 156 | + print(f"Download URL: {attachment_details['download_url']}") |
| 157 | + print(f"Expires At: {attachment_details['expires_at']}") |
| 158 | + else: |
| 159 | + print("\nNo attachments available to retrieve in this example.") |
| 160 | + |
| 161 | + |
| 162 | +if __name__ == "__main__": |
| 163 | + asyncio.run(main()) |
0 commit comments