agentmail 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/dist/cjs/Client.js +2 -2
  2. package/dist/cjs/api/resources/apiKeys/client/Client.js +3 -1
  3. package/dist/cjs/api/resources/domains/client/Client.js +3 -1
  4. package/dist/cjs/api/resources/domains/types/Domain.d.ts +1 -0
  5. package/dist/cjs/api/resources/domains/types/{DomainSummary.d.ts → DomainItem.d.ts} +2 -1
  6. package/dist/cjs/api/resources/domains/types/ListDomainsResponse.d.ts +2 -1
  7. package/dist/cjs/api/resources/domains/types/index.d.ts +1 -1
  8. package/dist/cjs/api/resources/domains/types/index.js +1 -1
  9. package/dist/cjs/api/resources/drafts/client/Client.js +6 -1
  10. package/dist/cjs/api/resources/inboxes/client/Client.js +6 -2
  11. package/dist/cjs/api/resources/inboxes/resources/drafts/client/Client.js +15 -4
  12. package/dist/cjs/api/resources/inboxes/resources/messages/client/Client.js +15 -4
  13. package/dist/cjs/api/resources/inboxes/resources/metrics/client/Client.js +3 -1
  14. package/dist/cjs/api/resources/inboxes/resources/threads/client/Client.js +6 -1
  15. package/dist/cjs/api/resources/inboxes/types/Inbox.d.ts +1 -0
  16. package/dist/cjs/api/resources/messages/types/ReplyToMessageRequest.d.ts +1 -0
  17. package/dist/cjs/api/resources/messages/types/SendMessageHeaders.d.ts +4 -0
  18. package/dist/cjs/api/resources/messages/types/SendMessageHeaders.js +3 -0
  19. package/dist/cjs/api/resources/messages/types/SendMessageRequest.d.ts +1 -0
  20. package/dist/cjs/api/resources/messages/types/index.d.ts +1 -0
  21. package/dist/cjs/api/resources/messages/types/index.js +1 -0
  22. package/dist/cjs/api/resources/metrics/client/Client.js +3 -1
  23. package/dist/cjs/api/resources/pods/client/Client.js +3 -1
  24. package/dist/cjs/api/resources/pods/resources/domains/client/Client.js +9 -2
  25. package/dist/cjs/api/resources/pods/resources/drafts/client/Client.js +6 -1
  26. package/dist/cjs/api/resources/pods/resources/inboxes/client/Client.js +9 -2
  27. package/dist/cjs/api/resources/pods/resources/threads/client/Client.js +6 -1
  28. package/dist/cjs/api/resources/threads/client/Client.js +6 -1
  29. package/dist/cjs/api/resources/webhooks/client/Client.js +3 -1
  30. package/dist/cjs/serialization/resources/domains/types/Domain.d.ts +2 -0
  31. package/dist/cjs/serialization/resources/domains/types/Domain.js +2 -0
  32. package/dist/cjs/serialization/resources/domains/types/{DomainSummary.d.ts → DomainItem.d.ts} +4 -2
  33. package/dist/cjs/serialization/resources/domains/types/{DomainSummary.js → DomainItem.js} +4 -2
  34. package/dist/cjs/serialization/resources/domains/types/ListDomainsResponse.d.ts +4 -2
  35. package/dist/cjs/serialization/resources/domains/types/ListDomainsResponse.js +4 -2
  36. package/dist/cjs/serialization/resources/domains/types/index.d.ts +1 -1
  37. package/dist/cjs/serialization/resources/domains/types/index.js +1 -1
  38. package/dist/cjs/serialization/resources/inboxes/types/Inbox.d.ts +2 -0
  39. package/dist/cjs/serialization/resources/inboxes/types/Inbox.js +2 -0
  40. package/dist/cjs/serialization/resources/messages/types/ReplyToMessageRequest.d.ts +2 -0
  41. package/dist/cjs/serialization/resources/messages/types/ReplyToMessageRequest.js +2 -0
  42. package/dist/cjs/serialization/resources/messages/types/SendMessageHeaders.d.ts +7 -0
  43. package/dist/cjs/serialization/resources/messages/types/SendMessageHeaders.js +39 -0
  44. package/dist/cjs/serialization/resources/messages/types/SendMessageRequest.d.ts +2 -0
  45. package/dist/cjs/serialization/resources/messages/types/SendMessageRequest.js +2 -0
  46. package/dist/cjs/serialization/resources/messages/types/index.d.ts +1 -0
  47. package/dist/cjs/serialization/resources/messages/types/index.js +1 -0
  48. package/dist/cjs/version.d.ts +1 -1
  49. package/dist/cjs/version.js +1 -1
  50. package/dist/esm/Client.mjs +2 -2
  51. package/dist/esm/api/resources/apiKeys/client/Client.mjs +3 -1
  52. package/dist/esm/api/resources/domains/client/Client.mjs +3 -1
  53. package/dist/esm/api/resources/domains/types/Domain.d.mts +1 -0
  54. package/dist/esm/api/resources/domains/types/{DomainSummary.d.mts → DomainItem.d.mts} +2 -1
  55. package/dist/esm/api/resources/domains/types/ListDomainsResponse.d.mts +2 -1
  56. package/dist/esm/api/resources/domains/types/index.d.mts +1 -1
  57. package/dist/esm/api/resources/domains/types/index.mjs +1 -1
  58. package/dist/esm/api/resources/drafts/client/Client.mjs +6 -1
  59. package/dist/esm/api/resources/inboxes/client/Client.mjs +6 -2
  60. package/dist/esm/api/resources/inboxes/resources/drafts/client/Client.mjs +15 -4
  61. package/dist/esm/api/resources/inboxes/resources/messages/client/Client.mjs +15 -4
  62. package/dist/esm/api/resources/inboxes/resources/metrics/client/Client.mjs +3 -1
  63. package/dist/esm/api/resources/inboxes/resources/threads/client/Client.mjs +6 -1
  64. package/dist/esm/api/resources/inboxes/types/Inbox.d.mts +1 -0
  65. package/dist/esm/api/resources/messages/types/ReplyToMessageRequest.d.mts +1 -0
  66. package/dist/esm/api/resources/messages/types/SendMessageHeaders.d.mts +4 -0
  67. package/dist/esm/api/resources/messages/types/SendMessageHeaders.mjs +2 -0
  68. package/dist/esm/api/resources/messages/types/SendMessageRequest.d.mts +1 -0
  69. package/dist/esm/api/resources/messages/types/index.d.mts +1 -0
  70. package/dist/esm/api/resources/messages/types/index.mjs +1 -0
  71. package/dist/esm/api/resources/metrics/client/Client.mjs +3 -1
  72. package/dist/esm/api/resources/pods/client/Client.mjs +3 -1
  73. package/dist/esm/api/resources/pods/resources/domains/client/Client.mjs +9 -2
  74. package/dist/esm/api/resources/pods/resources/drafts/client/Client.mjs +6 -1
  75. package/dist/esm/api/resources/pods/resources/inboxes/client/Client.mjs +9 -2
  76. package/dist/esm/api/resources/pods/resources/threads/client/Client.mjs +6 -1
  77. package/dist/esm/api/resources/threads/client/Client.mjs +6 -1
  78. package/dist/esm/api/resources/webhooks/client/Client.mjs +3 -1
  79. package/dist/esm/serialization/resources/domains/types/Domain.d.mts +2 -0
  80. package/dist/esm/serialization/resources/domains/types/Domain.mjs +2 -0
  81. package/dist/esm/serialization/resources/domains/types/{DomainSummary.d.mts → DomainItem.d.mts} +4 -2
  82. package/dist/esm/serialization/resources/domains/types/{DomainSummary.mjs → DomainItem.mjs} +3 -1
  83. package/dist/esm/serialization/resources/domains/types/ListDomainsResponse.d.mts +4 -2
  84. package/dist/esm/serialization/resources/domains/types/ListDomainsResponse.mjs +4 -2
  85. package/dist/esm/serialization/resources/domains/types/index.d.mts +1 -1
  86. package/dist/esm/serialization/resources/domains/types/index.mjs +1 -1
  87. package/dist/esm/serialization/resources/inboxes/types/Inbox.d.mts +2 -0
  88. package/dist/esm/serialization/resources/inboxes/types/Inbox.mjs +2 -0
  89. package/dist/esm/serialization/resources/messages/types/ReplyToMessageRequest.d.mts +2 -0
  90. package/dist/esm/serialization/resources/messages/types/ReplyToMessageRequest.mjs +2 -0
  91. package/dist/esm/serialization/resources/messages/types/SendMessageHeaders.d.mts +7 -0
  92. package/dist/esm/serialization/resources/messages/types/SendMessageHeaders.mjs +3 -0
  93. package/dist/esm/serialization/resources/messages/types/SendMessageRequest.d.mts +2 -0
  94. package/dist/esm/serialization/resources/messages/types/SendMessageRequest.mjs +2 -0
  95. package/dist/esm/serialization/resources/messages/types/index.d.mts +1 -0
  96. package/dist/esm/serialization/resources/messages/types/index.mjs +1 -0
  97. package/dist/esm/version.d.mts +1 -1
  98. package/dist/esm/version.mjs +1 -1
  99. package/dist/llms-full.txt +873 -81
  100. package/dist/llms.txt +2 -0
  101. package/package.json +1 -1
  102. /package/dist/cjs/api/resources/domains/types/{DomainSummary.js → DomainItem.js} +0 -0
  103. /package/dist/esm/api/resources/domains/types/{DomainSummary.mjs → DomainItem.mjs} +0 -0
@@ -130,7 +130,7 @@ AgentMail is an API-first email provider that is designed for agents. Think of i
130
130
  </Step>
131
131
  </Steps>
132
132
 
133
- Our customers use AgentMail for agent identity, authentication, and communication. To get started reach out to [contact@agentmail.cc](mailto:contact@agentmail.cc) for API keys and [support@agentmail.cc](mailto:support@agentmail.cc) for help.
133
+ Our customers use AgentMail for agent identity, authentication, and communication. To get started make an account on our [console](https://console.agentmail.to) and please email [support@agentmail.cc](mailto:support@agentmail.cc) if you run into any issues.
134
134
 
135
135
  <iframe width="560" height="315" src="https://www.youtube.com/embed/1V7BISeFUTM?si=4asiGnuV4O81nu5B" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen />
136
136
 
@@ -171,7 +171,7 @@ This guide will walk you through installing the AgentMail SDK, authenticating wi
171
171
  <Step title="Create an API Key">
172
172
  Now that you're in the console, you'll need to create an API key to
173
173
  authenticate your requests. Navigate to the API Keys section in your console
174
- dashboard. ![API Key Creation Screenshot](file:647e2f44-c63a-47a2-81eb-027d0d36aea4) Click
174
+ dashboard. ![API Key Creation Screenshot](file:f8c5320f-b15c-44e7-a569-670c5f1d2a88) Click
175
175
  "Create New API Key" and give it a descriptive name. Once created, copy the
176
176
  API key and store it securely. Create a `.env` file in your project's root
177
177
  directory and add your key to it. We recommend using environment variables to
@@ -312,7 +312,7 @@ Unlike traditional email providers that are designed for human scale, AgentMail
312
312
 
313
313
  As the diagram below illustrates, your `organization` is the top-level container that holds all your resources. You can provision many `Inboxes` within your `organization`, each with its own `Threads`, `Messages`, and `Attachments`, allowing you to manage a large fleet of agents seamlessly.
314
314
 
315
- <img src="file:e05c208a-738a-412f-a0e6-ee36b45d1c58" alt="AgentMail Organizational Hierarchy" />
315
+ <img src="file:ac426e5d-2c1a-40b1-bf52-5c97883187df" alt="AgentMail Organizational Hierarchy" />
316
316
 
317
317
  <Steps>
318
318
  <Step title="Organization">
@@ -732,7 +732,7 @@ Here is an example of a well-structured and styled HTML header:
732
732
  </CodeBlocks>
733
733
 
734
734
  <Frame caption="Look how pretty this message looks!">
735
- <img src="file:5048f406-a627-4265-b0af-dd051584c954" alt="rendered css" />
735
+ <img src="file:3e435f8a-5583-4ddd-83a3-c3f87c5f3aac" alt="rendered css" />
736
736
  </Frame>
737
737
 
738
738
  ## Receiving `Messages`
@@ -1759,7 +1759,7 @@ Configuring your domain is a three-step process: add the domain via API, copy th
1759
1759
  After creating your domain in the AgentMail Console, click the "Download BIND Zone File" button to get the complete zone file.
1760
1760
 
1761
1761
  <Frame caption="Downloading BIND zone file from AgentMail Console">
1762
- <img src="file:cdea45d4-68bf-4ba0-b5ca-335bf648cdcc" alt="Download BIND Zone File from Console" />
1762
+ <img src="file:fdcf475d-78f0-49a1-aa38-5bd877368f56" alt="Download BIND Zone File from Console" />
1763
1763
  </Frame>
1764
1764
 
1765
1765
  <Tabs>
@@ -1770,13 +1770,13 @@ Configuring your domain is a three-step process: add the domain via API, copy th
1770
1770
  2. Click **"Import zone file"** in the top right corner
1771
1771
 
1772
1772
  <Frame caption="Importing BIND zone file in AWS Route 53">
1773
- <img src="file:2a2170c9-a1ca-42df-9ae7-2f8be2b5786a" alt="AWS Route 53 BIND Import" />
1773
+ <img src="file:01476e8c-76ae-4414-b008-0547631c47f1" alt="AWS Route 53 BIND Import" />
1774
1774
  </Frame>
1775
1775
 
1776
1776
  3. Paste the CONTENTS of downloaded BIND zone file
1777
1777
 
1778
1778
  <Frame caption="Open the file with text editor and paste the contents. It should look similar to what we have in this image.">
1779
- <img src="file:a45bcc2c-6233-4810-b421-f05ff7d1d9e2" alt="AWS Route 53 BIND Import" />
1779
+ <img src="file:86767929-19ef-4ded-b528-ed42ede218fe" alt="AWS Route 53 BIND Import" />
1780
1780
  </Frame>
1781
1781
 
1782
1782
  4. Review the records and click **"Import"**
@@ -1789,13 +1789,13 @@ Configuring your domain is a three-step process: add the domain via API, copy th
1789
1789
  2. Navigate to **DNS > Records**
1790
1790
 
1791
1791
  <Frame caption="This is what the page looks like">
1792
- <img src="file:188c4275-664e-4191-938b-cfd43be0b5af" alt="Cloudflare BIND Import" />
1792
+ <img src="file:1886368e-04ae-4bfe-a117-83246de25118" alt="Cloudflare BIND Import" />
1793
1793
  </Frame>
1794
1794
 
1795
1795
  3. Click **"Import and Export"**
1796
1796
 
1797
1797
  <Frame caption="You should be able to just drop the file in">
1798
- <img src="file:24aa7c24-9fec-4270-94d6-53216596f05b" alt="Cloudflare BIND Import" />
1798
+ <img src="file:b966738e-c0e6-425d-86d1-0ce95b9a326d" alt="Cloudflare BIND Import" />
1799
1799
  </Frame>
1800
1800
 
1801
1801
  4. Upload the downloaded BIND zone file as is
@@ -1808,13 +1808,13 @@ Configuring your domain is a three-step process: add the domain via API, copy th
1808
1808
  2. Navigate to the **DNS** subtab of the domain you want to send from
1809
1809
 
1810
1810
  <Frame caption="Click on this button!">
1811
- <img src="file:60fc16e7-57d3-4836-926a-ad412278e979" alt="Porkbun DNS Management" />
1811
+ <img src="file:57da42f8-9541-4e8a-9b20-7c81ca585355" alt="Porkbun DNS Management" />
1812
1812
  </Frame>
1813
1813
 
1814
1814
  3. Scroll down to the quick upload section
1815
1815
 
1816
1816
  <Frame caption="Upload your BIND zone file here">
1817
- <img src="file:fa0d13d1-d8d2-4c7c-a772-ff1a9f5defe8" alt="Porkbun Zone File Import" />
1817
+ <img src="file:2824bdf3-c4c7-4dfe-b67a-1373865ecf22" alt="Porkbun Zone File Import" />
1818
1818
  </Frame>
1819
1819
 
1820
1820
  4. Upload the downloaded BIND zone file as is
@@ -1898,7 +1898,7 @@ Configuring your domain is a three-step process: add the domain via API, copy th
1898
1898
  * **Value:** Can directly copy paste the `value` from the API response (e.g., `{random_letters_numbers}.dkim.amazonses.com`).
1899
1899
 
1900
1900
  <Frame caption="Example of adding a CNAME record in Route 53. Notice that AWS already appends the root domain (agentmail.cc) to the end of the name value!">
1901
- <img src="file:7b5a4349-f189-48b4-b76b-57acdc3adda9" alt="AWS Route 53 Record Configuration" />
1901
+ <img src="file:62bea4af-5b5e-4f88-86ce-b569f26f8a74" alt="AWS Route 53 Record Configuration" />
1902
1902
  </Frame>
1903
1903
 
1904
1904
  * **TXT (DMARC/SPF):**
@@ -2008,7 +2008,7 @@ DNS can be tricky. Here are some common issues and how to resolve them.
2008
2008
 
2009
2009
  ## Best Practices for Domain Management
2010
2010
 
2011
- Check out our guide on [Email Deliverability](/best-practices/email-deliverability) for tips on warming up your new domain and maintaining a healthy sender reputation.
2011
+ Check out our guide on [Email Deliverability](/email-deliverability) for tips on warming up your new domain and maintaining a healthy sender reputation.
2012
2012
 
2013
2013
 
2014
2014
  # Managing Your Domains
@@ -2434,13 +2434,13 @@ Ngrok creates a secure tunnel from a public URL to your local development server
2434
2434
 
2435
2435
  Visit [ngrok.com](https://ngrok.com/) and click "Sign up" to create a free account.
2436
2436
 
2437
- <img src="file:4bc85b25-98e4-47b6-8634-b10c99126a74" alt="Ngrok homepage" />
2437
+ <img src="file:845efbdc-7a3b-44be-b7b6-d85c15baabfd" alt="Ngrok homepage" />
2438
2438
 
2439
2439
  ### 1.2 Choose your platform and install
2440
2440
 
2441
2441
  After logging in, ngrok will guide you through the setup process. Select your operating system and follow the installation instructions.
2442
2442
 
2443
- <img src="file:694649d0-b6ed-4078-ade0-57160c1df709" alt="Ngrok setup instructions" />
2443
+ <img src="file:6bf31cc4-f08c-4b45-9abd-b93966def3ab" alt="Ngrok setup instructions" />
2444
2444
 
2445
2445
  For macOS, you can install ngrok via Homebrew:
2446
2446
 
@@ -2486,7 +2486,7 @@ ngrok http 3000
2486
2486
 
2487
2487
  You should see output similar to this:
2488
2488
 
2489
- <img src="file:18d605b1-a8f1-4680-adc0-f67da20a0e09" alt="Ngrok terminal output" />
2489
+ <img src="file:190c3920-7025-4399-8718-b2b9a4895382" alt="Ngrok terminal output" />
2490
2490
 
2491
2491
  Copy the **Forwarding URL** (e.g., `https://your-subdomain.ngrok-free.app`). This is the public URL that AgentMail will use to send webhooks.
2492
2492
 
@@ -2583,7 +2583,7 @@ python webhook_receiver.py
2583
2583
 
2584
2584
  Open your browser and visit `http://127.0.0.1:3000` to see the status page confirming your webhook receiver is running:
2585
2585
 
2586
- <img src="file:e1bdd83f-8e7f-48b0-836e-4488e36a5fae" alt="Webhook receiver status page" />
2586
+ <img src="file:933ee151-1684-4e56-b2a9-4dd7e81f9f5d" alt="Webhook receiver status page" />
2587
2587
 
2588
2588
  ## Testing Your Setup
2589
2589
 
@@ -2705,7 +2705,7 @@ How you send your emails is just as important as what you send. If you're sendin
2705
2705
  more natural to email providers. AgentMail's ability to create inboxes at
2706
2706
  scale makes this strategy easy to implement.
2707
2707
 
2708
- <img src="file:8daee71e-d560-475e-a2f6-6ba191425a0a" alt="Diagram comparing one inbox sending 1000 emails vs. five inboxes sending 200 each." />
2708
+ <img src="file:256ac0e7-42b8-4fdd-a3f1-6136fbec2725" alt="Diagram comparing one inbox sending 1000 emails vs. five inboxes sending 200 each." />
2709
2709
  </Step>
2710
2710
 
2711
2711
  <Step title="Protect Your Reputation with Multiple Domains">
@@ -2825,7 +2825,7 @@ We will use Flask to create a simple web server and `ngrok` to expose it to the
2825
2825
  Before you start, make sure you have the following:
2826
2826
 
2827
2827
  * Python 3.8+
2828
- * An [AgentMail API Key](mailto:contact@agentmail.to).
2828
+ * An [AgentMail API Key](https://console.agentmail.to/dashboard/api-keys).
2829
2829
  * An [OpenAI account](https://openai.com/) and API key.
2830
2830
  * An [ngrok account](https://ngrok.com/) and authtoken.
2831
2831
 
@@ -2898,15 +2898,15 @@ Create a file named `main.py` and add the full code example you provided. This s
2898
2898
 
2899
2899
  target_github_repo = os.getenv("TARGET_GITHUB_REPO")
2900
2900
  if not target_github_repo:
2901
- print("\nWARNING: The TARGET_GITHUB_REPO environment variable is not set.")
2902
- print("The agent will not have a specific GitHub repository to focus on.")
2903
- print("Please set it in your .env file (e.g., TARGET_GITHUB_REPO='owner/repository_name')\n")
2901
+ print("\nWARNING: The TARGET_GITHUB_REPO environment variable is not set.")
2902
+ print("The agent will not have a specific GitHub repository to focus on.")
2903
+ print("Please set it in your .env file (e.g., TARGET_GITHUB_REPO='owner/repository_name')\n")
2904
2904
 
2905
2905
  demo_target_email = os.getenv("DEMO_TARGET_EMAIL")
2906
2906
  if not demo_target_email:
2907
- print("\nWARNING: The DEMO_TARGET_EMAIL environment variable is not set.")
2908
- print("The agent will not have a specific email to send the 'top starrer' outreach to.")
2909
- print("Please set it in your .env file (e.g., DEMO_TARGET_EMAIL='your.email@example.com')\n")
2907
+ print("\nWARNING: The DEMO_TARGET_EMAIL environment variable is not set.")
2908
+ print("The agent will not have a specific email to send the 'top starrer' outreach to.")
2909
+ print("Please set it in your .env file (e.g., DEMO_TARGET_EMAIL='your.email@example.com')\n")
2910
2910
 
2911
2911
  # Determine the target email, with a fallback if the environment variable is not set.
2912
2912
 
@@ -2933,13 +2933,13 @@ Create a file named `main.py` and add the full code example you provided. This s
2933
2933
  inbox_client_id = f"inbox-for-{inbox_username}"
2934
2934
  print(f"Attempting to create or retrieve inbox '{inbox}' with client_id: {inbox_client_id}")
2935
2935
  try:
2936
- client.inboxes.create(
2937
- username=inbox_username,
2938
- client_id=inbox_client_id
2939
- )
2940
- print("Inbox creation/retrieval successful.")
2936
+ client.inboxes.create(
2937
+ username=inbox_username,
2938
+ client_id=inbox_client_id
2939
+ )
2940
+ print("Inbox creation/retrieval successful.")
2941
2941
  except Exception as e:
2942
- print(f"Error creating/retrieving inbox: {e}") # Depending on the desired behavior, you might want to exit here # if the inbox is critical for the agent's function.
2942
+ print(f"Error creating/retrieving inbox: {e}") # Depending on the desired behavior, you might want to exit here # if the inbox is critical for the agent's function.
2943
2943
 
2944
2944
  # 3. Start the ngrok tunnel to get a public URL
2945
2945
 
@@ -2953,13 +2953,13 @@ Create a file named `main.py` and add the full code example you provided. This s
2953
2953
  webhook_client_id = f"webhook-for-{inbox_username}"
2954
2954
  print(f"Attempting to create or retrieve webhook for URL: {webhook_url}")
2955
2955
  try:
2956
- client.webhooks.create(
2957
- url=webhook_url,
2958
- client_id=webhook_client_id,
2959
- )
2960
- print("Webhook creation/retrieval successful.")
2956
+ client.webhooks.create(
2957
+ url=webhook_url,
2958
+ client_id=webhook_client_id,
2959
+ )
2960
+ print("Webhook creation/retrieval successful.")
2961
2961
  except Exception as e:
2962
- print(f"Error creating/retrieving webhook: {e}")
2962
+ print(f"Error creating/retrieving webhook: {e}")
2963
2963
 
2964
2964
  # 5. Initialize the Flask App
2965
2965
 
@@ -3015,9 +3015,9 @@ Create a file named `main.py` and add the full code example you provided. This s
3015
3015
  """
3016
3016
 
3017
3017
  agent = Agent(
3018
- name="GitHub Agent",
3019
- instructions=instructions,
3020
- tools=AgentMailToolkit(client).get_tools() + [WebSearchTool()],
3018
+ name="GitHub Agent",
3019
+ instructions=instructions,
3020
+ tools=AgentMailToolkit(client).get_tools() + [WebSearchTool()],
3021
3021
  )
3022
3022
 
3023
3023
  messages = []
@@ -3029,8 +3029,8 @@ Create a file named `main.py` and add the full code example you provided. This s
3029
3029
  stars_found_so_far = 0
3030
3030
 
3031
3031
  def poll_github_stargazers():
3032
- global simulated_stargazer_count, stars_found_so_far
3033
- print(f"GitHub polling thread started for top 20 repositories related to AI agents...")
3032
+ global simulated_stargazer_count, stars_found_so_far
3033
+ print(f"GitHub polling thread started for top 20 repositories related to AI agents...")
3034
3034
 
3035
3035
  # Give the Flask app a moment to start up if run concurrently
3036
3036
  time.sleep(3)
@@ -3104,12 +3104,12 @@ Create a file named `main.py` and add the full code example you provided. This s
3104
3104
 
3105
3105
  @app.route("/webhooks", methods=["POST"])
3106
3106
  def receive_webhook():
3107
- print(f"\n[/webhooks] Received webhook. Payload keys: {list(request.json.keys()) if request.is_json else 'Not JSON or empty'}")
3108
- Thread(target=process_webhook, args=(request.json,)).start()
3109
- return Response(status=200)
3107
+ print(f"\n[/webhooks] Received webhook. Payload keys: {list(request.json.keys()) if request.is_json else 'Not JSON or empty'}")
3108
+ Thread(target=process_webhook, args=(request.json,)).start()
3109
+ return Response(status=200)
3110
3110
 
3111
3111
  def process_webhook(payload):
3112
- global messages
3112
+ global messages
3113
3113
 
3114
3114
  email = payload["message"]
3115
3115
  print(f"[process_webhook] Processing email from: {email.get('from')}, subject: {email.get('subject')}, id: {email.get('message_id')}")
@@ -3131,12 +3131,12 @@ Create a file named `main.py` and add the full code example you provided. This s
3131
3131
  messages = response.to_input_list()
3132
3132
  print(f"[process_webhook] Updated message history. New length: {len(messages)}\n")
3133
3133
 
3134
- if __name__ == "__main__":
3135
- print(f"Inbox: {inbox}\n")
3136
- if not target_github_repo or target_github_repo == "example/repo":
3137
- print("WARNING: TARGET_GITHUB_REPO not set or is default. Poller will not be effective.")
3138
- if not demo_target_email:
3139
- print("WARNING: DEMO_TARGET_EMAIL not set or is default. Poller will not be effective.")
3134
+ if **name** == "**main**":
3135
+ print(f"Inbox: {inbox}\n")
3136
+ if not target_github_repo or target_github_repo == "example/repo":
3137
+ print("WARNING: TARGET_GITHUB_REPO not set or is default. Poller will not be effective.")
3138
+ if not demo_target_email:
3139
+ print("WARNING: DEMO_TARGET_EMAIL not set or is default. Poller will not be effective.")
3140
3140
 
3141
3141
  polling_thread = Thread(target=poll_github_stargazers)
3142
3142
  polling_thread.daemon = True # So it exits when the main thread exits
@@ -3293,6 +3293,7 @@ Create a file named `agent.py` and paste the following code:
3293
3293
  from flask import Flask, request, Response
3294
3294
  import ngrok
3295
3295
  from agentmail import AgentMail
3296
+ import threading
3296
3297
 
3297
3298
  # Configuration
3298
3299
  PORT = 8080
@@ -3302,6 +3303,7 @@ Create a file named `agent.py` and paste the following code:
3302
3303
  # Initialize Flask app and AgentMail client
3303
3304
  app = Flask(__name__)
3304
3305
  client = AgentMail()
3306
+ processed_messages = set() # Track processed message IDs to prevent duplicates
3305
3307
 
3306
3308
 
3307
3309
  def setup_agentmail():
@@ -3334,6 +3336,7 @@ Create a file named `agent.py` and paste the following code:
3334
3336
  webhook = client.webhooks.create(
3335
3337
  url=f"{listener.url()}/webhook/agentmail",
3336
3338
  event_types=["message.received"],
3339
+ inbox_ids=[inbox.inbox_id],
3337
3340
  client_id=f"{INBOX_USERNAME}-webhook"
3338
3341
  )
3339
3342
  print(f"✓ Webhook created")
@@ -3361,25 +3364,8 @@ Create a file named `agent.py` and paste the following code:
3361
3364
  )
3362
3365
 
3363
3366
 
3364
- @app.route('/webhook/agentmail', methods=['POST'])
3365
- def receive_webhook():
3366
- """Webhook endpoint to receive incoming email notifications."""
3367
- payload = request.json
3368
- event_type = payload.get('type') or payload.get('event_type')
3369
-
3370
- # Ignore outgoing messages
3371
- if event_type == 'message.sent':
3372
- return Response(status=200)
3373
-
3374
- message = payload.get('message', {})
3375
- message_id = message.get('message_id')
3376
- inbox_id = message.get('inbox_id')
3377
- from_field = message.get('from_', '') or message.get('from', '')
3378
-
3379
- # Validate required fields
3380
- if not message_id or not inbox_id or not from_field:
3381
- return Response(status=200)
3382
-
3367
+ def process_and_reply(message_id, inbox_id, from_field, subject, message):
3368
+ """Process incoming message and send reply in background."""
3383
3369
  # Extract sender email and name
3384
3370
  if '<' in from_field and '>' in from_field:
3385
3371
  sender_email = from_field.split('<')[1].split('>')[0].strip()
@@ -3390,10 +3376,8 @@ Create a file named `agent.py` and paste the following code:
3390
3376
  sender_email = from_field.strip()
3391
3377
  sender_name = sender_email.split('@')[0].title() if '@' in sender_email else 'Friend'
3392
3378
 
3393
- subject = message.get('subject', '(no subject)')
3394
-
3395
3379
  # Log incoming email
3396
- print(f"Email from {sender_email}: {subject}")
3380
+ print(f"Processing email from {sender_email}: {subject}")
3397
3381
 
3398
3382
  # Generate and send auto-reply
3399
3383
  try:
@@ -3408,6 +3392,41 @@ Create a file named `agent.py` and paste the following code:
3408
3392
  except Exception as e:
3409
3393
  print(f"Error: {e}\n")
3410
3394
 
3395
+
3396
+ @app.route('/webhook/agentmail', methods=['POST'])
3397
+ def receive_webhook():
3398
+ """Webhook endpoint to receive incoming email notifications."""
3399
+ payload = request.json
3400
+ event_type = payload.get('type') or payload.get('event_type')
3401
+
3402
+ # Ignore outgoing messages
3403
+ if event_type == 'message.sent':
3404
+ return Response(status=200)
3405
+
3406
+ message = payload.get('message', {})
3407
+ message_id = message.get('message_id')
3408
+ inbox_id = message.get('inbox_id')
3409
+ from_field = message.get('from_', '') or message.get('from', '')
3410
+
3411
+ # Validate required fields
3412
+ if not message_id or not inbox_id or not from_field:
3413
+ return Response(status=200)
3414
+
3415
+ # prevent duplicate
3416
+ if message_id in processed_messages:
3417
+ return Response(status=200)
3418
+ processed_messages.add(message_id)
3419
+
3420
+ subject = message.get('subject', '(no subject)')
3421
+
3422
+ # Process in background thread and return immediately
3423
+ thread = threading.Thread(
3424
+ target=process_and_reply,
3425
+ args=(message_id, inbox_id, from_field, subject, message)
3426
+ )
3427
+ thread.daemon = True
3428
+ thread.start()
3429
+
3411
3430
  return Response(status=200)
3412
3431
 
3413
3432
 
@@ -4705,7 +4724,7 @@ Done
4705
4724
 
4706
4725
  Go to your AgentMail inbox and filter by labels to organize your emails:
4707
4726
 
4708
- <img src="file:6467fddc-96b2-4aa9-b2fe-5e16fba7af9e" alt="Test image" />
4727
+ <img src="file:0cf3d744-bb78-46de-acc7-e3de13a39cf9" alt="Test image" />
4709
4728
 
4710
4729
  **Filter by sentiment:**
4711
4730
 
@@ -4875,12 +4894,545 @@ Ready to build your own intelligent email agent? Check out our [quickstart guide
4875
4894
  </AccordionGroup>
4876
4895
 
4877
4896
 
4897
+ # Email Reply Extraction with Talon
4898
+
4899
+ > Learn how to use Talon to extract new content from email replies, removing quoted text with 93.8% accuracy.
4900
+
4901
+ ## Why Talon?
4902
+
4903
+ Email threads accumulate quoted replies that clutter the actual content. When processing emails programmatically, you need just the new message, not the entire conversation history.
4904
+
4905
+ **Talon solves this problem** by extracting clean reply content through sophisticated pattern matching and structural analysis.
4906
+
4907
+ ### Use Cases
4908
+
4909
+ * **AI Email Agents**: Extract new user messages without processing entire thread history
4910
+ * **Email Automation**: Parse replies to identify actionable content
4911
+ * **Thread Analysis**: Build conversation flows by isolating individual contributions
4912
+ * **Inbox Management**: Process only new information from replies
4913
+
4914
+ ### Why Choose Talon?
4915
+
4916
+ <CardGroup cols={2}>
4917
+ <Card title="HTML Email Support" icon="fa-regular fa-file-code">
4918
+ Handles Gmail, Outlook, Apple Mail, Thunderbird HTML structures
4919
+ </Card>
4920
+
4921
+ <Card title="High Accuracy" icon="fa-regular fa-bullseye">
4922
+ 93.8% success rate across 64 real-world test cases
4923
+ </Card>
4924
+
4925
+ <Card title="Multi-language" icon="fa-regular fa-globe">
4926
+ Supports English, Japanese, Swedish, Polish, Dutch, German
4927
+ </Card>
4928
+
4929
+ <Card title="Fast Performance" icon="fa-regular fa-gauge-high">
4930
+ 1.92ms average processing time, 488 emails/second
4931
+ </Card>
4932
+ </CardGroup>
4933
+
4934
+ ***
4935
+
4936
+ ## How Talon Works
4937
+
4938
+ Talon uses two complementary approaches depending on email format:
4939
+
4940
+ ### Plain Text Processing (6-Stage Pipeline)
4941
+
4942
+ 1. **Line Classification**: Assigns markers to each line ('t'=text, 'm'=quote marker, 's'=splitter, 'e'=empty)
4943
+ 2. **Pattern Matching**: Applies regex to marker sequences to identify quoted blocks
4944
+ 3. **Content Extraction**: Removes quoted lines and returns clean text
4945
+
4946
+ Recognizes patterns like:
4947
+
4948
+ * Standard quote markers (`>`)
4949
+ * Reply headers ("On \[date] \[name] wrote:")
4950
+ * Forward indicators ("-----Original Message-----")
4951
+
4952
+ ### HTML Processing (8-Stage Pipeline)
4953
+
4954
+ 1. **Structural Removal**: Directly removes known quotation elements (Gmail divs, blockquotes, Outlook markup)
4955
+ 2. **Checkpoint Fallback**: For non-standard HTML, maps elements to text lines, applies text patterns, removes corresponding HTML
4956
+
4957
+ ### Processing Systems
4958
+
4959
+ **Quotation Removal** (Primary)
4960
+
4961
+ * Removes quoted replies from thread
4962
+ * No initialization required
4963
+ * Rule-based pattern matching
4964
+
4965
+ ***
4966
+
4967
+ ## Getting Started
4968
+
4969
+ <Steps>
4970
+ <Step title="Install Talon">
4971
+ Install via pip with required workaround for Python 3.11+:
4972
+
4973
+ <CodeBlocks>
4974
+ ```bash
4975
+ pip install talon
4976
+ ```
4977
+ </CodeBlocks>
4978
+ </Step>
4979
+
4980
+ <Step title="Apply Python 3.11+ Workaround">
4981
+ Required fix for cchardet dependency:
4982
+
4983
+ <CodeBlocks>
4984
+ ```python
4985
+ # Import workaround BEFORE importing talon
4986
+ import sys
4987
+ import chardet
4988
+ sys.modules['cchardet'] = chardet
4989
+
4990
+ # Now safe to import talon
4991
+ import talon
4992
+ from talon import quotations
4993
+ ```
4994
+ </CodeBlocks>
4995
+
4996
+ <Callout intent="warn">
4997
+ This workaround is **required** for Python 3.11+.
4998
+ </Callout>
4999
+ </Step>
5000
+
5001
+ <Step title="Extract Reply Content">
5002
+ Basic usage for plain text and HTML:
5003
+
5004
+ <CodeBlocks>
5005
+ ```python title="Plain Text"
5006
+ from talon import quotations
5007
+
5008
+ email = """Great work on the project!
5009
+
5010
+ On Mon, Apr 11, 2011 at 6:54 PM, Bob wrote:
5011
+ > Can you review the document?
5012
+ > Need feedback by Friday.
5013
+ """
5014
+
5015
+ clean_reply = quotations.extract_from_plain(email)
5016
+ # Result: "Great work on the project!"
5017
+ ```
5018
+
5019
+ ```python title="HTML"
5020
+ from talon import quotations
5021
+
5022
+ html_email = """
5023
+ <html><body>
5024
+ <div>Thanks for the update!</div>
5025
+ <div class="gmail_quote">
5026
+ <div>On Mon, Alice wrote:</div>
5027
+ <blockquote>Original message here</blockquote>
5028
+ </div>
5029
+ </body></html>
5030
+ """
5031
+
5032
+ clean_html = quotations.extract_from_html(html_email)
5033
+ # Returns: <html><body><div>Thanks for the update!</div></body></html>
5034
+ ```
5035
+ </CodeBlocks>
5036
+ </Step>
5037
+ </Steps>
5038
+
5039
+ ***
5040
+
5041
+ ## Performance & Accuracy
5042
+
5043
+ Talon has been tested on 64 real-world emails from various clients and languages.
5044
+
5045
+ ### Test Results Summary
5046
+
5047
+ | Metric | Value |
5048
+ | ----------------------- | ------------------- |
5049
+ | **Total Tests** | 64 emails |
5050
+ | **Passed** | 60 (93.8%) |
5051
+ | **Failed** | 4 (6.2%) |
5052
+ | **Avg Processing Time** | 1.92ms |
5053
+ | **Throughput** | 488.6 emails/second |
5054
+ | **Min/Max Time** | 0.13ms - 21.55ms |
5055
+
5056
+ ### Test Coverage
5057
+
5058
+ * **22 HTML emails**: Gmail, Outlook, Apple Mail, Thunderbird, Mail.ru, Hotmail
5059
+ * **42 plain text emails**: Various formats and reply styles
5060
+ * **6+ languages**: English, Japanese, Swedish, Polish, Dutch, German
5061
+ * **Mobile clients**: iPhone, Android "Sent from" signatures
5062
+
5063
+ ### Processing Time by Complexity
5064
+
5065
+ | Email Type | Avg Time | Complexity |
5066
+ | ------------------ | --------- | ---------- |
5067
+ | Simple text reply | 0.2-0.5ms | Low |
5068
+ | HTML Gmail/Outlook | 2-4ms | Medium |
5069
+ | Complex threads | 4-22ms | High |
5070
+
5071
+ ### Speed vs Accuracy Tradeoff
5072
+
5073
+ | Library | Avg Processing Time | Accuracy | Best For |
5074
+ | ------------ | ------------------- | -------- | --------------------------------------- |
5075
+ | **Talon** | 1.92ms | 93.8% | Production systems needing HTML support |
5076
+ | qutoequail | 0.96ms | \~85% | Moderate accuracy requirements |
5077
+ | Custom regex | 0.1ms | \~70% | Simple plain text, speed critical |
5078
+
5079
+ **Insight**: For production systems, 1.92ms average is negligible. Even at worst case (21.55ms), Talon is faster than most network requests.
5080
+
5081
+ ***
5082
+
5083
+ ## Known Limitations
5084
+
5085
+ Talon failed 4 out of 64 test cases. Here's what didn't work:
5086
+
5087
+ <AccordionGroup>
5088
+ <Accordion title="Failed Test Cases (4 total)">
5089
+ ### Test Case 1: Complex Email Thread with Mixed Content
5090
+
5091
+ **Input**:
5092
+
5093
+ ```text
5094
+ Thank you, Sonya Johnson.
5095
+
5096
+ I have sent an invite for 10:30am Monday PDT (today). I
5097
+ hope you can join.
5098
+
5099
+ Regards,
5100
+
5101
+ Christopher Edwards
5102
+
5103
+
5104
+ On Mon, Jun 3, 2024 at 12:53 AM Cody Hart <omerritt@example.com> wrote:
5105
+
5106
+ > Hi Christopher Edwards,
5107
+ >
5108
+ > 10.30 AM pacific is good for me.
5109
+ >
5110
+ > Thanks & Regards,
5111
+ >
5112
+ > Cody Hart
5113
+ ```
5114
+
5115
+ **Expected Output**: First 5 lines only (up to `Christopher Edwards`)
5116
+
5117
+ **Talon's Output**: Returns entire email including quoted text starting with "On Mon, Jun 3..." and all "> quoted text"
5118
+
5119
+ **Processing Time**: 2.55ms
5120
+
5121
+ **Issue**: Signature placement before quotes confuses detection logic
5122
+
5123
+ ***
5124
+
5125
+ ### Test Case 2: Inline Responses
5126
+
5127
+ **Input**:
5128
+
5129
+ ```text
5130
+ On Tue, Apr 29, 2014 at 4:22 PM, Example Dev <sugar@example.com> wrote:
5131
+
5132
+ > okay. Well, here's some stuff I can write.
5133
+ >
5134
+ > And if I write a 2 second line you and maybe reply under this?
5135
+ >
5136
+ > Or if you didn't really feel like it, you could reply under this line.
5137
+
5138
+ I will reply under this one
5139
+
5140
+ >
5141
+ > okay?
5142
+ >
5143
+
5144
+ and under this.
5145
+
5146
+ >
5147
+ > -- Tim
5148
+ ```
5149
+
5150
+ **Expected Output**: Just the inline responses (`I will reply under this one` and `and under this.`)
5151
+
5152
+ **Talon's Output**: Returns everything including "On Tue, Apr 29..." header and all quoted lines
5153
+
5154
+ **Processing Time**: 0.48ms
5155
+
5156
+ **Issue**: Interleaved inline responses not recognized as the reply pattern
5157
+
5158
+ ***
5159
+
5160
+ ### Test Case 3: Gmail Forward HTML
5161
+
5162
+ **Input**:
5163
+
5164
+ ```html
5165
+ <html><head></head><body><div dir="ltr">test<div><br /></div><div>blah</div>
5166
+ <div><br /><div class="gmail_quote">---------- Forwarded message ----------<br />
5167
+ From: <b class="gmail_sendername">Foo Bar</b>
5168
+ <span dir="ltr">&lt;<a href="mailto:foo@bar.example">foo@bar.example</a>&gt;</span><br />
5169
+ Date: Thu, Mar 24, 2016 at 5:17 PM<br />
5170
+ Subject: The Subject<br />
5171
+ To: John Doe &lt;<a href="mailto:john@doe.example">john@doe.example</a>&gt;<br />
5172
+ <br /><br /><div dir="ltr">Some text<div><br /></div><div><br /></div></div>
5173
+ </div><br /></div></div></body></html>
5174
+ ```
5175
+
5176
+ **Expected Output**: Just `testblah` (before the forward marker)
5177
+
5178
+ **Talon's Output**: Includes "---------- Forwarded message ----------" and forwarded content
5179
+
5180
+ **Processing Time**: 3.41ms
5181
+
5182
+ **Issue**: HTML forward headers not removed by Gmail quote detection
5183
+
5184
+ ***
5185
+
5186
+ ### Test Case 4: Thunderbird Forward HTML
5187
+
5188
+ **Input**:
5189
+
5190
+ ```html
5191
+ <html><body bgcolor="#FFFFFF" text="#000000">
5192
+ <p><br /></p>
5193
+ <div class="moz-forward-container"><br /><br />
5194
+ -------- Forwarded Message --------
5195
+ <table class="moz-email-headers-table">
5196
+ <tbody>
5197
+ <tr><th>Subject:</th><td>Re: Example subject</td></tr>
5198
+ <tr><th>Date:</th><td>Tue, 3 May 2016 14:54:27 +0200 (CEST)</td></tr>
5199
+ <tr><th>From:</th><td>John Doe &lt;johndoe@example.com&gt;</td></tr>
5200
+ </tbody>
5201
+ </table>
5202
+ <br /><br />
5203
+ <div>Dear John,</div>
5204
+ <div><br /></div>
5205
+ <div>This is a test.</div>
5206
+ </div></body></html>
5207
+ ```
5208
+
5209
+ **Expected Output**: Empty (no new content, just forward)
5210
+
5211
+ **Talon's Output**: Includes "-------- Forwarded Message --------" and forwarded content
5212
+
5213
+ **Processing Time**: 4.34ms
5214
+
5215
+ **Issue**: Thunderbird's `moz-forward-container` class not recognized
5216
+
5217
+ ***
5218
+
5219
+ **Summary**: 3 of 4 failures are forwarded messages. Regular replies work with 98%+ accuracy.
5220
+ </Accordion>
5221
+
5222
+ <Accordion title="Success Examples">
5223
+ ### Example 1: Simple Gmail Reply
5224
+
5225
+ **Input**:
5226
+
5227
+ ```text
5228
+ Awesome! I haven't had another problem with it.
5229
+
5230
+ On Aug 22, 2011, at 7:37 PM, defunkt<reply@reply.github.com> wrote:
5231
+
5232
+
5233
+
5234
+
5235
+ > Loader seems to be working well.
5236
+ ```
5237
+
5238
+ **Talon's Output**: `Awesome! I haven't had another problem with it.`
5239
+
5240
+ **Processing Time**: 0.2ms
5241
+
5242
+ **What Worked**: Standard "On \[date] \[name] wrote:" pattern detected, quote marker (>) recognized
5243
+
5244
+ ***
5245
+
5246
+ ### Example 2: Outlook Reply with Separator
5247
+
5248
+ **Input**:
5249
+
5250
+ ```text
5251
+ Outlook with a reply directly above line
5252
+ ________________________________________
5253
+ From: CRM Comments [crm-comment@example.com]
5254
+ Sent: Friday, 23 March 2012 5:08 p.m.
5255
+ To: John S. Greene
5256
+ Subject: [contact:106] John Greene
5257
+
5258
+ A new comment has been added to the Contact named 'John Greene':
5259
+
5260
+ I am replying to a comment.
5261
+ ```
5262
+
5263
+ **Talon's Output**: `Outlook with a reply directly above line`
5264
+
5265
+ **Processing Time**: 0.51ms
5266
+
5267
+ **What Worked**: Outlook separator line (underscores) and "From:"/"Sent:" headers detected as splitter
5268
+
5269
+ ***
5270
+
5271
+ ### Example 3: HTML Outlook Reply
5272
+
5273
+ **Input**:
5274
+
5275
+ ```html
5276
+ <html>
5277
+ <body>
5278
+ <div>Reply</div>
5279
+ <span id="OLK_SRC_BODY_SECTION">
5280
+ <div>
5281
+ <span>From: </span>Bob &lt;<a href="mailto:bob@example.com">bob@example.com</a>&gt;<br />
5282
+ <span>Date: </span>Tue, 01 Nov 2011 18:54:39 -0700<br />
5283
+ <span>To: </span>Rob &lt;<a href="mailto:rob@example.com">rob@example.com</a>&gt;<br />
5284
+ <span>Subject: </span>Test<br />
5285
+ </div>
5286
+ <div>Hi</div>
5287
+ </span>
5288
+ </body>
5289
+ </html>
5290
+ ```
5291
+
5292
+ **Talon's Output**: `Reply`
5293
+
5294
+ **Processing Time**: 4.02ms
5295
+
5296
+ **What Worked**: Outlook's `OLK_SRC_BODY_SECTION` span ID detected and removed structurally
5297
+ </Accordion>
5298
+
5299
+ <Accordion title="Performance vs Simpler Alternatives">
5300
+ **Tradeoff**: Talon is more comprehensive but slower than plain-text-only libraries
5301
+
5302
+ * Talon: 1.92ms average (with HTML support)
5303
+ * email-reply-parser: 0.03ms average (plain text only)
5304
+
5305
+ For production systems, 1.92ms average is negligible. Even at worst case (21.55ms), Talon is faster than most network requests.
5306
+ </Accordion>
5307
+
5308
+ <Accordion title="Forwarded Messages">
5309
+ As shown in test results, forwarded messages (especially HTML) are challenging:
5310
+
5311
+ * Plain text forwards: Generally work well
5312
+ * HTML forwards: May retain forward headers
5313
+ * Workaround: Use plain text extraction or post-process to remove forward markers
5314
+ </Accordion>
5315
+ </AccordionGroup>
5316
+
5317
+ ***
5318
+
5319
+ ### Error Handling
5320
+
5321
+ Always handle potential parsing failures:
5322
+
5323
+ ```python
5324
+ from talon import quotations
5325
+
5326
+ def safe_extract(email_body, is_html=False):
5327
+ try:
5328
+ if is_html:
5329
+ return quotations.extract_from_html(email_body)
5330
+ else:
5331
+ return quotations.extract_from_plain(email_body)
5332
+ except Exception as e:
5333
+ # Fallback to original message if extraction fails
5334
+ print(f"Talon extraction failed: {e}")
5335
+ return email_body
5336
+ ```
5337
+
5338
+ ### Testing Recommendations
5339
+
5340
+ Always test with your specific email formats:
5341
+
5342
+ ```python
5343
+ # Create a test suite with your actual email patterns (Gmail, Outlook, Apple Mail)
5344
+ test_emails = [
5345
+ "path/to/gmail_reply.html",
5346
+ "path/to/outlook_reply.txt",
5347
+ "path/to/forward.html"
5348
+ ]
5349
+
5350
+ for email_file in test_emails:
5351
+ with open(email_file) as f:
5352
+ content = f.read()
5353
+ result = quotations.extract_from(content)
5354
+ print(f"{email_file}: {len(result)} chars extracted")
5355
+ ```
5356
+
5357
+ <Tip>
5358
+ Test with real emails from your users' actual email clients. Talon's accuracy is based on diverse real-world samples, but your specific use case may have unique patterns.
5359
+ </Tip>
5360
+
5361
+ ***
5362
+
5363
+ ## JavaScript Version
5364
+
5365
+ For TypeScript/JavaScript projects, use **[TalonJS](https://github.com/quentez/talonjs)** - a JavaScript port of Talon with similar functionality.
5366
+
5367
+ ### Performance Comparison
5368
+
5369
+ | Solution | Accuracy | Speed | Best For |
5370
+ | ---------------- | -------- | ------ | --------------------------- |
5371
+ | **Python Talon** | 93.8% | 1.92ms | Highest accuracy |
5372
+ | **TalonJS** | 90.6% | 1.88ms | TypeScript/Node.js projects |
5373
+
5374
+ TalonJS provides 90.6% accuracy with slightly faster performance (1.88ms), making it ideal for JavaScript/TypeScript environments without needing Python dependencies.
5375
+
5376
+ ### Quick Start
5377
+
5378
+ <Steps>
5379
+ <Step title="Install TalonJS">
5380
+ ```bash
5381
+ npm install talonjs
5382
+ ```
5383
+ </Step>
5384
+
5385
+ <Step title="Extract Replies">
5386
+ <CodeBlocks>
5387
+ ```typescript title="Plain Text"
5388
+ import * as talon from 'talonjs';
5389
+
5390
+ const email = `Great work on the project!
5391
+
5392
+ On Mon, Apr 11, 2011 at 6:54 PM, Bob wrote:
5393
+ > Can you review the document?
5394
+ > Need feedback by Friday.
5395
+ `;
5396
+
5397
+ const result = talon.quotations.extractFromPlain(email);
5398
+ const cleanReply = result.body.trim();
5399
+ // Output: "Great work on the project!"
5400
+ ```
5401
+
5402
+ ```typescript title="HTML"
5403
+ import * as talon from 'talonjs';
5404
+
5405
+ const htmlEmail = `
5406
+ <div>Thanks for the update!</div>
5407
+ <div class="gmail_quote">
5408
+ On Mon, Alice wrote: <blockquote>Original</blockquote>
5409
+ </div>
5410
+ `;
5411
+
5412
+ const result = talon.quotations.extractFromHtml(htmlEmail);
5413
+ const cleanReply = result.body.trim();
5414
+ // Returns: "<div>Thanks for the update!</div>"
5415
+ // Note: TalonJS returns clean HTML, not plain text
5416
+ ```
5417
+ </CodeBlocks>
5418
+ </Step>
5419
+ </Steps>
5420
+
5421
+ <Tip>
5422
+ **When to use TalonJS vs Python Talon:**
5423
+
5424
+ * Use **TalonJS** if you're building in TypeScript/JavaScript and 90.6% accuracy is sufficient
5425
+ * Use **Python Talon** if you need the highest accuracy (93.8%) or are in a Python environment
5426
+ * The 3.2% accuracy difference is acceptable for most use cases
5427
+ </Tip>
5428
+
5429
+
4878
5430
  # Join the AgentMail Community
4879
5431
 
4880
5432
  > Connect with the AgentMail team and developers, share what you're building, and get support.
4881
5433
 
4882
5434
  <CardGroup>
4883
- <Card title="Join our Discord Server" href="https://discord.gg/your-invite-code" icon="fa-brands fa-discord">
5435
+ <Card title="Join our Discord Server" href="https://discord.com/invite/hTYatWYWBc" icon="fa-brands fa-discord">
4884
5436
  The best place for real-time conversation, getting help with your code, and
4885
5437
  sharing what you're building with AgentMail.
4886
5438
  </Card>
@@ -4899,7 +5451,7 @@ Ready to build your own intelligent email agent? Check out our [quickstart guide
4899
5451
  <Callout title="Premium Support for Customers" intent="info" icon="fa-brands fa-slack">
4900
5452
  For purchasing customers, we offer dedicated support channels to ensure your success. Get priority assistance, custom integration help, and a private Slack channel with our core engineering team.
4901
5453
 
4902
- To learn more about our premium plans and dedicated support options, please email us at [contact@agentmail.to](mailto:contact@agentmail.to).
5454
+ To learn more about our premium plans and dedicated support options, please visit our website [here](https://agentmail.to/pricing).
4903
5455
  </Callout>
4904
5456
 
4905
5457
 
@@ -5678,6 +6230,242 @@ let dataTask = session.dataTask(with: request as URLRequest, completionHandler:
5678
6230
  dataTask.resume()
5679
6231
  ```
5680
6232
 
6233
+ # Update Inbox
6234
+
6235
+ PATCH https://api.agentmail.to/v0/inboxes/{inbox_id}
6236
+ Content-Type: application/json
6237
+
6238
+ Reference: https://docs.agentmail.to/api-reference/inboxes/update
6239
+
6240
+ ## OpenAPI Specification
6241
+
6242
+ ```yaml
6243
+ openapi: 3.1.1
6244
+ info:
6245
+ title: Update Inbox
6246
+ version: endpoint_inboxes.update
6247
+ paths:
6248
+ /v0/inboxes/{inbox_id}:
6249
+ patch:
6250
+ operationId: update
6251
+ summary: Update Inbox
6252
+ tags:
6253
+ - - subpackage_inboxes
6254
+ parameters:
6255
+ - name: inbox_id
6256
+ in: path
6257
+ required: true
6258
+ schema:
6259
+ $ref: '#/components/schemas/type_inboxes:InboxId'
6260
+ - name: Authorization
6261
+ in: header
6262
+ description: >-
6263
+ Bearer authentication of the form `Bearer <token>`, where token is
6264
+ your auth token.
6265
+ required: true
6266
+ schema:
6267
+ type: string
6268
+ responses:
6269
+ '200':
6270
+ description: Response with status 200
6271
+ content:
6272
+ application/json:
6273
+ schema:
6274
+ $ref: '#/components/schemas/type_inboxes:Inbox'
6275
+ '404':
6276
+ description: Error response with status 404
6277
+ content: {}
6278
+ requestBody:
6279
+ content:
6280
+ application/json:
6281
+ schema:
6282
+ $ref: '#/components/schemas/type_inboxes:UpdateInboxRequest'
6283
+ components:
6284
+ schemas:
6285
+ type_inboxes:InboxId:
6286
+ type: string
6287
+ type_inboxes:DisplayName:
6288
+ type: string
6289
+ type_inboxes:UpdateInboxRequest:
6290
+ type: object
6291
+ properties:
6292
+ display_name:
6293
+ $ref: '#/components/schemas/type_inboxes:DisplayName'
6294
+ required:
6295
+ - display_name
6296
+ type_inboxes:ClientId:
6297
+ type: string
6298
+ type_inboxes:Inbox:
6299
+ type: object
6300
+ properties:
6301
+ inbox_id:
6302
+ $ref: '#/components/schemas/type_inboxes:InboxId'
6303
+ display_name:
6304
+ $ref: '#/components/schemas/type_inboxes:DisplayName'
6305
+ client_id:
6306
+ $ref: '#/components/schemas/type_inboxes:ClientId'
6307
+ updated_at:
6308
+ type: string
6309
+ format: date-time
6310
+ created_at:
6311
+ type: string
6312
+ format: date-time
6313
+ required:
6314
+ - inbox_id
6315
+ - updated_at
6316
+ - created_at
6317
+
6318
+ ```
6319
+
6320
+ ## SDK Code Examples
6321
+
6322
+ ```typescript
6323
+ import { AgentMailClient } from "agentmail";
6324
+
6325
+ async function main() {
6326
+ const client = new AgentMailClient({
6327
+ environment: "https://api.agentmail.to",
6328
+ apiKey: "YOUR_TOKEN_HERE",
6329
+ });
6330
+ await client.inboxes.update("inbox_id", {
6331
+ displayName: "display_name",
6332
+ });
6333
+ }
6334
+ main();
6335
+
6336
+ ```
6337
+
6338
+ ```python
6339
+ from agentmail import AgentMail
6340
+
6341
+ client = AgentMail(
6342
+ base_url="https://api.agentmail.to",
6343
+ api_key="YOUR_TOKEN_HERE"
6344
+ )
6345
+
6346
+ client.inboxes.update(
6347
+ inbox_id="inbox_id",
6348
+ display_name="display_name"
6349
+ )
6350
+
6351
+ ```
6352
+
6353
+ ```go
6354
+ package main
6355
+
6356
+ import (
6357
+ "fmt"
6358
+ "strings"
6359
+ "net/http"
6360
+ "io"
6361
+ )
6362
+
6363
+ func main() {
6364
+
6365
+ url := "https://api.agentmail.to/v0/inboxes/inbox_id"
6366
+
6367
+ payload := strings.NewReader("{\n \"display_name\": \"display_name\"\n}")
6368
+
6369
+ req, _ := http.NewRequest("PATCH", url, payload)
6370
+
6371
+ req.Header.Add("Authorization", "Bearer <api_key>")
6372
+ req.Header.Add("Content-Type", "application/json")
6373
+
6374
+ res, _ := http.DefaultClient.Do(req)
6375
+
6376
+ defer res.Body.Close()
6377
+ body, _ := io.ReadAll(res.Body)
6378
+
6379
+ fmt.Println(res)
6380
+ fmt.Println(string(body))
6381
+
6382
+ }
6383
+ ```
6384
+
6385
+ ```ruby
6386
+ require 'uri'
6387
+ require 'net/http'
6388
+
6389
+ url = URI("https://api.agentmail.to/v0/inboxes/inbox_id")
6390
+
6391
+ http = Net::HTTP.new(url.host, url.port)
6392
+ http.use_ssl = true
6393
+
6394
+ request = Net::HTTP::Patch.new(url)
6395
+ request["Authorization"] = 'Bearer <api_key>'
6396
+ request["Content-Type"] = 'application/json'
6397
+ request.body = "{\n \"display_name\": \"display_name\"\n}"
6398
+
6399
+ response = http.request(request)
6400
+ puts response.read_body
6401
+ ```
6402
+
6403
+ ```java
6404
+ HttpResponse<String> response = Unirest.patch("https://api.agentmail.to/v0/inboxes/inbox_id")
6405
+ .header("Authorization", "Bearer <api_key>")
6406
+ .header("Content-Type", "application/json")
6407
+ .body("{\n \"display_name\": \"display_name\"\n}")
6408
+ .asString();
6409
+ ```
6410
+
6411
+ ```php
6412
+ <?php
6413
+
6414
+ $client = new \GuzzleHttp\Client();
6415
+
6416
+ $response = $client->request('PATCH', 'https://api.agentmail.to/v0/inboxes/inbox_id', [
6417
+ 'body' => '{
6418
+ "display_name": "display_name"
6419
+ }',
6420
+ 'headers' => [
6421
+ 'Authorization' => 'Bearer <api_key>',
6422
+ 'Content-Type' => 'application/json',
6423
+ ],
6424
+ ]);
6425
+
6426
+ echo $response->getBody();
6427
+ ```
6428
+
6429
+ ```csharp
6430
+ var client = new RestClient("https://api.agentmail.to/v0/inboxes/inbox_id");
6431
+ var request = new RestRequest(Method.PATCH);
6432
+ request.AddHeader("Authorization", "Bearer <api_key>");
6433
+ request.AddHeader("Content-Type", "application/json");
6434
+ request.AddParameter("application/json", "{\n \"display_name\": \"display_name\"\n}", ParameterType.RequestBody);
6435
+ IRestResponse response = client.Execute(request);
6436
+ ```
6437
+
6438
+ ```swift
6439
+ import Foundation
6440
+
6441
+ let headers = [
6442
+ "Authorization": "Bearer <api_key>",
6443
+ "Content-Type": "application/json"
6444
+ ]
6445
+ let parameters = ["display_name": "display_name"] as [String : Any]
6446
+
6447
+ let postData = JSONSerialization.data(withJSONObject: parameters, options: [])
6448
+
6449
+ let request = NSMutableURLRequest(url: NSURL(string: "https://api.agentmail.to/v0/inboxes/inbox_id")! as URL,
6450
+ cachePolicy: .useProtocolCachePolicy,
6451
+ timeoutInterval: 10.0)
6452
+ request.httpMethod = "PATCH"
6453
+ request.allHTTPHeaderFields = headers
6454
+ request.httpBody = postData as Data
6455
+
6456
+ let session = URLSession.shared
6457
+ let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
6458
+ if (error != nil) {
6459
+ print(error as Any)
6460
+ } else {
6461
+ let httpResponse = response as? HTTPURLResponse
6462
+ print(httpResponse)
6463
+ }
6464
+ })
6465
+
6466
+ dataTask.resume()
6467
+ ```
6468
+
5681
6469
  # Delete Inbox
5682
6470
 
5683
6471
  DELETE https://api.agentmail.to/v0/inboxes/{inbox_id}
@@ -12694,7 +13482,7 @@ components:
12694
13482
  type: boolean
12695
13483
  type_domains:ClientId:
12696
13484
  type: string
12697
- type_domains:DomainSummary:
13485
+ type_domains:DomainItem:
12698
13486
  type: object
12699
13487
  properties:
12700
13488
  domain_id:
@@ -12719,12 +13507,14 @@ components:
12719
13507
  properties:
12720
13508
  count:
12721
13509
  $ref: '#/components/schemas/type_:Count'
13510
+ limit:
13511
+ $ref: '#/components/schemas/type_:Limit'
12722
13512
  next_page_token:
12723
13513
  $ref: '#/components/schemas/type_:PageToken'
12724
13514
  domains:
12725
13515
  type: array
12726
13516
  items:
12727
- $ref: '#/components/schemas/type_domains:DomainSummary'
13517
+ $ref: '#/components/schemas/type_domains:DomainItem'
12728
13518
  required:
12729
13519
  - count
12730
13520
  - domains
@@ -20457,7 +21247,7 @@ components:
20457
21247
  type: boolean
20458
21248
  type_domains:ClientId:
20459
21249
  type: string
20460
- type_domains:DomainSummary:
21250
+ type_domains:DomainItem:
20461
21251
  type: object
20462
21252
  properties:
20463
21253
  domain_id:
@@ -20482,12 +21272,14 @@ components:
20482
21272
  properties:
20483
21273
  count:
20484
21274
  $ref: '#/components/schemas/type_:Count'
21275
+ limit:
21276
+ $ref: '#/components/schemas/type_:Limit'
20485
21277
  next_page_token:
20486
21278
  $ref: '#/components/schemas/type_:PageToken'
20487
21279
  domains:
20488
21280
  type: array
20489
21281
  items:
20490
- $ref: '#/components/schemas/type_domains:DomainSummary'
21282
+ $ref: '#/components/schemas/type_domains:DomainItem'
20491
21283
  required:
20492
21284
  - count
20493
21285
  - domains