{"id":278392,"date":"2026-04-27T17:19:42","date_gmt":"2026-04-27T15:19:42","guid":{"rendered":"https:\/\/www.unipile.com\/?p=278392"},"modified":"2026-04-28T17:25:47","modified_gmt":"2026-04-28T15:25:47","slug":"envoyer-un-e-mail-api-python","status":"publish","type":"post","link":"https:\/\/www.unipile.com\/fr\/send-email-api-python\/","title":{"rendered":"Comment envoyer des e-mails via une API en Python (Tutoriel rapide)"},"content":{"rendered":"\n[et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.27.3&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;20px|0px|0px|0px|false|false&#8221; da_disable_devices=&#8221;off|off|off&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221; da_is_popup=&#8221;off&#8221; da_exit_intent=&#8221;off&#8221; da_has_close=&#8221;on&#8221; da_alt_close=&#8221;off&#8221; da_dark_close=&#8221;off&#8221; da_not_modal=&#8221;on&#8221; da_is_singular=&#8221;off&#8221; da_with_loader=&#8221;off&#8221; da_has_shadow=&#8221;on&#8221;][et_pb_row _builder_version=&#8221;4.27.3&#8243; max_width=&#8221;100%&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_code _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;]<style><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->#upl-toc-pyapi, #upl-toc-pyapi *, #upl-toc-pyapi *::before, #upl-toc-pyapi *::after {<!-- [et_pb_line_break_holder] -->  margin:0!important;padding:0!important;box-sizing:border-box!important;border:none!important;<!-- [et_pb_line_break_holder] -->  outline:none!important;font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif!important;<!-- [et_pb_line_break_holder] -->  line-height:normal!important;letter-spacing:normal!important;text-transform:none!important;<!-- [et_pb_line_break_holder] -->  text-decoration:none!important;list-style:none!important;background:transparent!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi { max-width:1100px!important;margin:0 auto!important;padding:0 20px 8px!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-card { background:#fff!important;border-radius:14px!important;border:1px solid #e2e5ea!important;overflow:hidden!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-mobile-toggle { display:none!important;align-items:center!important;justify-content:space-between!important;padding:14px 18px!important;cursor:pointer!important;background:#fff!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-mobile-label { font-family:'Poppins',sans-serif!important;font-size:0.8rem!important;font-weight:700!important;color:#0f2736!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-mobile-icon { color:#64748b!important;transition:transform 0.3s!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-collapsible { display:block!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-header { display:flex!important;align-items:center!important;justify-content:space-between!important;padding:14px 18px 10px!important;border-bottom:1px solid #f0f1f3!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-header-title { font-family:'Poppins',sans-serif!important;font-size:0.72rem!important;font-weight:700!important;color:#0f2736!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-badge { background:rgba(59,185,139,0.12)!important;color:#3BB98B!important;font-size:0.52rem!important;font-weight:700!important;padding:3px 8px!important;border-radius:20px!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-grid { display:grid!important;grid-template-columns:repeat(4,1fr)!important;gap:0!important;padding:6px 6px 10px!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-col { padding:12px!important;border-left:1px solid #f0f1f3!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-col:first-child { border-left:none!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-label { font-size:0.52rem!important;font-weight:700!important;color:#94a3b8!important;text-transform:uppercase!important;letter-spacing:1px!important;margin-bottom:8px!important;display:block!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-link { display:flex!important;align-items:center!important;gap:7px!important;padding:5px 6px!important;border-radius:6px!important;color:#64748b!important;font-size:0.68rem!important;font-weight:500!important;cursor:pointer!important;margin-bottom:2px!important;transition:background 0.15s!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-link:hover { background:rgba(59,185,139,0.06)!important;color:#0f2736!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-link.utcp-active { background:rgba(59,185,139,0.08)!important;color:#0f2736!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-num { width:18px!important;height:18px!important;min-width:18px!important;border-radius:5px!important;background:#f1f5f9!important;font-size:0.55rem!important;font-weight:700!important;color:#94a3b8!important;display:flex!important;align-items:center!important;justify-content:center!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-link.utcp-active .utcp-num { background:#3BB98B!important;color:#fff!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-link-text { flex:1!important; }<!-- [et_pb_line_break_holder] -->#upl-toc-pyapi .utcp-tag-rec { background:rgba(59,185,139,0.12)!important;color:#3BB98B!important;font-size:0.45rem!important;font-weight:700!important;padding:2px 5px!important;border-radius:4px!important; }<!-- [et_pb_line_break_holder] -->@media(max-width:1000px){ #upl-toc-pyapi .utcp-grid { grid-template-columns:repeat(2,1fr)!important; } }<!-- [et_pb_line_break_holder] -->@media(max-width:700px){<!-- [et_pb_line_break_holder] -->  #upl-toc-pyapi .utcp-mobile-toggle { display:flex!important; }<!-- [et_pb_line_break_holder] -->  #upl-toc-pyapi .utcp-collapsible { display:none!important; }<!-- [et_pb_line_break_holder] -->  #upl-toc-pyapi .utcp-collapsible.open { display:block!important; }<!-- [et_pb_line_break_holder] -->  #upl-toc-pyapi .utcp-grid { grid-template-columns:1fr!important; }<!-- [et_pb_line_break_holder] -->  #upl-toc-pyapi .utcp-col { border-left:none!important;border-top:1px solid #f0f1f3!important; }<!-- [et_pb_line_break_holder] -->  #upl-toc-pyapi .utcp-col:first-child { border-top:none!important; }<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><\/style><!-- [et_pb_line_break_holder] --><div id=\"upl-toc-pyapi\"><!-- [et_pb_line_break_holder] -->  <div class=\"utcp-card\"><!-- [et_pb_line_break_holder] -->    <div class=\"utcp-mobile-toggle\" onclick=\"var c=this.nextElementSibling;c.classList.toggle('open');this.querySelector('.utcp-mobile-icon').style.transform=c.classList.contains('open')?'rotate(180deg)':'rotate(0)'\"><!-- [et_pb_line_break_holder] -->      <span class=\"utcp-mobile-label\">Table of Contents<\/span><!-- [et_pb_line_break_holder] -->      <svg class=\"utcp-mobile-icon\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><polyline points=\"6 9 12 15 18 9\"><\/polyline><\/svg><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->    <div class=\"utcp-collapsible\"><!-- [et_pb_line_break_holder] -->      <div class=\"utcp-header\"><!-- [et_pb_line_break_holder] -->        <span class=\"utcp-header-title\">Table of Contents<\/span><!-- [et_pb_line_break_holder] -->        <span class=\"utcp-badge\">11 sections<\/span><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"utcp-grid\"><!-- [et_pb_line_break_holder] -->        <div class=\"utcp-col\"><!-- [et_pb_line_break_holder] -->          <span class=\"utcp-label\">Getting Started<\/span><!-- [et_pb_line_break_holder] -->          <div class=\"utcp-link utcp-active\" onclick=\"document.getElementById('anchor-tldr').scrollIntoView({behavior:'smooth'})\"><span class=\"utcp-num\">01<\/span><span class=\"utcp-link-text\">TL;DR &#8211; 5-Line Example<\/span><span class=\"utcp-tag-rec\">Quick<\/span><\/div><!-- [et_pb_line_break_holder] -->          <div class=\"utcp-link\" onclick=\"document.getElementById('anchor-prereqs').scrollIntoView({behavior:'smooth'})\"><span class=\"utcp-num\">02<\/span><span class=\"utcp-link-text\">Prerequisites &#038; Setup<\/span><\/div><!-- [et_pb_line_break_holder] -->          <div class=\"utcp-link\" onclick=\"document.getElementById('anchor-connect').scrollIntoView({behavior:'smooth'})\"><span class=\"utcp-num\">03<\/span><span class=\"utcp-link-text\">Connect First Account<\/span><\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"utcp-col\"><!-- [et_pb_line_break_holder] -->          <span class=\"utcp-label\">Sending Emails<\/span><!-- [et_pb_line_break_holder] -->          <div class=\"utcp-link\" onclick=\"document.getElementById('anchor-send').scrollIntoView({behavior:'smooth'})\"><span class=\"utcp-num\">04<\/span><span class=\"utcp-link-text\">Send Your First Email<\/span><span class=\"utcp-tag-rec\">Core<\/span><\/div><!-- [et_pb_line_break_holder] -->          <div class=\"utcp-link\" onclick=\"document.getElementById('anchor-attachments').scrollIntoView({behavior:'smooth'})\"><span class=\"utcp-num\">05<\/span><span class=\"utcp-link-text\">Attachments in Python<\/span><\/div><!-- [et_pb_line_break_holder] -->          <div class=\"utcp-link\" onclick=\"document.getElementById('anchor-advanced').scrollIntoView({behavior:'smooth'})\"><span class=\"utcp-num\">06<\/span><span class=\"utcp-link-text\">Replies, Threads &#038; Tracking<\/span><\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"utcp-col\"><!-- [et_pb_line_break_holder] -->          <span class=\"utcp-label\">Production<\/span><!-- [et_pb_line_break_holder] -->          <div class=\"utcp-link\" onclick=\"document.getElementById('anchor-errors').scrollIntoView({behavior:'smooth'})\"><span class=\"utcp-num\">07<\/span><span class=\"utcp-link-text\">Error Handling &#038; Retries<\/span><\/div><!-- [et_pb_line_break_holder] -->          <div class=\"utcp-link\" onclick=\"document.getElementById('anchor-security').scrollIntoView({behavior:'smooth'})\"><span class=\"utcp-num\">08<\/span><span class=\"utcp-link-text\">Security Best Practices<\/span><\/div><!-- [et_pb_line_break_holder] -->          <div class=\"utcp-link\" onclick=\"document.getElementById('anchor-pitfalls').scrollIntoView({behavior:'smooth'})\"><span class=\"utcp-num\">09<\/span><span class=\"utcp-link-text\">Common Python Pitfalls<\/span><\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"utcp-col\"><!-- [et_pb_line_break_holder] -->          <span class=\"utcp-label\">Reference<\/span><!-- [et_pb_line_break_holder] -->          <div class=\"utcp-link\" onclick=\"document.getElementById('anchor-faq').scrollIntoView({behavior:'smooth'})\"><span class=\"utcp-num\">10<\/span><span class=\"utcp-link-text\">FAQ<\/span><\/div><!-- [et_pb_line_break_holder] -->          <div class=\"utcp-link\" onclick=\"document.getElementById('anchor-final-cta').scrollIntoView({behavior:'smooth'})\"><span class=\"utcp-num\">11<\/span><span class=\"utcp-link-text\">Start Building<\/span><\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] --><\/div>[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.27.3&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;0px|0px|0px|0px|false|false&#8221; da_disable_devices=&#8221;off|off|off&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221; da_is_popup=&#8221;off&#8221; da_exit_intent=&#8221;off&#8221; da_has_close=&#8221;on&#8221; da_alt_close=&#8221;off&#8221; da_dark_close=&#8221;off&#8221; da_not_modal=&#8221;on&#8221; da_is_singular=&#8221;off&#8221; da_with_loader=&#8221;off&#8221; da_has_shadow=&#8221;on&#8221;][et_pb_row _builder_version=&#8221;4.27.3&#8243; max_width=&#8221;100%&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_code _builder_version=&#8221;4.27.4&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;]<style><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->#upl-hero-pyapi, #upl-hero-pyapi *, #upl-hero-pyapi *::before, #upl-hero-pyapi *::after {<!-- [et_pb_line_break_holder] -->  margin:0!important;padding:0!important;box-sizing:border-box!important;border:none!important;<!-- [et_pb_line_break_holder] -->  outline:none!important;font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif!important;<!-- [et_pb_line_break_holder] -->  line-height:normal!important;letter-spacing:normal!important;text-transform:none!important;<!-- [et_pb_line_break_holder] -->  text-decoration:none!important;list-style:none!important;background:transparent!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi {<!-- [et_pb_line_break_holder] -->  padding:64px 20px 72px!important;<!-- [et_pb_line_break_holder] -->  background:#f4f5f7!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-inner {<!-- [et_pb_line_break_holder] -->  max-width:1160px!important;<!-- [et_pb_line_break_holder] -->  margin:0 auto!important;<!-- [et_pb_line_break_holder] -->  display:grid!important;<!-- [et_pb_line_break_holder] -->  grid-template-columns:1fr 1fr!important;<!-- [et_pb_line_break_holder] -->  gap:56px!important;<!-- [et_pb_line_break_holder] -->  align-items:center!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-eyebrow {<!-- [et_pb_line_break_holder] -->  display:inline-flex!important;<!-- [et_pb_line_break_holder] -->  align-items:center!important;<!-- [et_pb_line_break_holder] -->  gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:rgba(221,223,76,0.18)!important;<!-- [et_pb_line_break_holder] -->  color:#8a8c2e!important;<!-- [et_pb_line_break_holder] -->  padding:6px 14px!important;<!-- [et_pb_line_break_holder] -->  border-radius:20px!important;<!-- [et_pb_line_break_holder] -->  font-size:12px!important;<!-- [et_pb_line_break_holder] -->  font-weight:700!important;<!-- [et_pb_line_break_holder] -->  text-transform:uppercase!important;<!-- [et_pb_line_break_holder] -->  letter-spacing:0.5px!important;<!-- [et_pb_line_break_holder] -->  margin-bottom:20px!important;<!-- [et_pb_line_break_holder] -->  width:fit-content!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-eyebrow .hpy-dot {<!-- [et_pb_line_break_holder] -->  width:7px!important;height:7px!important;<!-- [et_pb_line_break_holder] -->  background:#DDDF4C!important;<!-- [et_pb_line_break_holder] -->  border-radius:50%!important;<!-- [et_pb_line_break_holder] -->  flex-shrink:0!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-h1 {<!-- [et_pb_line_break_holder] -->  font-family:'Poppins',sans-serif!important;<!-- [et_pb_line_break_holder] -->  font-size:44px!important;<!-- [et_pb_line_break_holder] -->  font-weight:700!important;<!-- [et_pb_line_break_holder] -->  color:#0f2736!important;<!-- [et_pb_line_break_holder] -->  line-height:1.18!important;<!-- [et_pb_line_break_holder] -->  margin-bottom:20px!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-h1 .hpy-accent { color:#3BB98B!important; }<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-desc {<!-- [et_pb_line_break_holder] -->  font-size:17px!important;<!-- [et_pb_line_break_holder] -->  line-height:1.75!important;<!-- [et_pb_line_break_holder] -->  color:#383838!important;<!-- [et_pb_line_break_holder] -->  margin-bottom:24px!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-desc a {<!-- [et_pb_line_break_holder] -->  color:#3BB98B!important;<!-- [et_pb_line_break_holder] -->  font-weight:600!important;<!-- [et_pb_line_break_holder] -->  text-decoration:underline!important;<!-- [et_pb_line_break_holder] -->  text-decoration-color:rgba(59,185,139,0.4)!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-meta {<!-- [et_pb_line_break_holder] -->  display:flex!important;<!-- [et_pb_line_break_holder] -->  align-items:center!important;<!-- [et_pb_line_break_holder] -->  gap:16px!important;<!-- [et_pb_line_break_holder] -->  flex-wrap:wrap!important;<!-- [et_pb_line_break_holder] -->  margin-bottom:20px!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-meta-item {<!-- [et_pb_line_break_holder] -->  display:flex!important;<!-- [et_pb_line_break_holder] -->  align-items:center!important;<!-- [et_pb_line_break_holder] -->  gap:6px!important;<!-- [et_pb_line_break_holder] -->  font-size:0.8rem!important;<!-- [et_pb_line_break_holder] -->  color:#718096!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-meta-item svg {<!-- [et_pb_line_break_holder] -->  width:14px!important;height:14px!important;<!-- [et_pb_line_break_holder] -->  stroke:#3BB98B!important;fill:none!important;<!-- [et_pb_line_break_holder] -->  stroke-width:2!important;stroke-linecap:round!important;stroke-linejoin:round!important;<!-- [et_pb_line_break_holder] -->  flex-shrink:0!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-meta-sep {<!-- [et_pb_line_break_holder] -->  width:4px!important;height:4px!important;<!-- [et_pb_line_break_holder] -->  background:#cbd5e0!important;border-radius:50%!important;flex-shrink:0!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-tags {<!-- [et_pb_line_break_holder] -->  display:flex!important;flex-wrap:wrap!important;gap:8px!important;margin-bottom:28px!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-tag {<!-- [et_pb_line_break_holder] -->  background:#ffffff!important;color:#4a5568!important;<!-- [et_pb_line_break_holder] -->  padding:5px 12px!important;border-radius:6px!important;<!-- [et_pb_line_break_holder] -->  font-size:0.75rem!important;font-weight:500!important;<!-- [et_pb_line_break_holder] -->  border:1px solid #e2e8f0!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-actions {<!-- [et_pb_line_break_holder] -->  display:flex!important;align-items:center!important;gap:14px!important;flex-wrap:wrap!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-cta-primary {<!-- [et_pb_line_break_holder] -->  display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:#DDDF4C!important;color:#0f2736!important;<!-- [et_pb_line_break_holder] -->  padding:14px 28px!important;border-radius:8px!important;<!-- [et_pb_line_break_holder] -->  font-size:0.95rem!important;font-weight:600!important;<!-- [et_pb_line_break_holder] -->  border:2px solid #DDDF4C!important;<!-- [et_pb_line_break_holder] -->  transition:all 0.3s ease!important;cursor:pointer!important;<!-- [et_pb_line_break_holder] -->  white-space:nowrap!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-cta-primary:hover { transform:translateY(-5px)!important; }<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-cta-primary svg { width:16px!important;height:16px!important;stroke:currentColor!important;fill:none!important;stroke-width:2.5!important;stroke-linecap:round!important;stroke-linejoin:round!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-cta-secondary {<!-- [et_pb_line_break_holder] -->  display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:transparent!important;color:#0f2736!important;<!-- [et_pb_line_break_holder] -->  padding:12px 24px!important;border-radius:8px!important;<!-- [et_pb_line_break_holder] -->  border:2px solid #0f2736!important;<!-- [et_pb_line_break_holder] -->  font-size:0.95rem!important;font-weight:600!important;<!-- [et_pb_line_break_holder] -->  transition:all 0.3s ease!important;cursor:pointer!important;<!-- [et_pb_line_break_holder] -->  white-space:nowrap!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-cta-secondary:hover { background:#0f2736!important;color:#ffffff!important; }<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-cta-secondary svg { width:16px!important;height:16px!important;stroke:currentColor!important;fill:none!important;stroke-width:2.5!important;stroke-linecap:round!important;stroke-linejoin:round!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-editor {<!-- [et_pb_line_break_holder] -->  border-radius:14px!important;overflow:hidden!important;<!-- [et_pb_line_break_holder] -->  background:#0d1117!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-editor-bar {<!-- [et_pb_line_break_holder] -->  background:#161b22!important;padding:12px 18px!important;<!-- [et_pb_line_break_holder] -->  display:flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  border-bottom:1px solid rgba(255,255,255,0.06)!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-dot-r {width:12px!important;height:12px!important;border-radius:50%!important;background:#ff5f57!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-dot-y {width:12px!important;height:12px!important;border-radius:50%!important;background:#febc2e!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-dot-g {width:12px!important;height:12px!important;border-radius:50%!important;background:#28c840!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-filename {<!-- [et_pb_line_break_holder] -->  color:#8b949e!important;font-size:13px!important;margin-left:6px!important;<!-- [et_pb_line_break_holder] -->  font-family:'Courier New',monospace!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-pre {<!-- [et_pb_line_break_holder] -->  padding:22px 24px!important;font-size:13px!important;<!-- [et_pb_line_break_holder] -->  line-height:1.8!important;overflow-x:auto!important;background:#0d1117!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-pre code {<!-- [et_pb_line_break_holder] -->  font-family:'Courier New',monospace!important;white-space:pre!important;display:block!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-c {color:#8b949e!important;}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-k {color:#ff7b72!important;}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-fn {color:#d2a8ff!important;}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-s {color:#a5d6ff!important;}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-w {color:#e6edf3!important;}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-n {color:#79c0ff!important;}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-editor-ok {<!-- [et_pb_line_break_holder] -->  background:rgba(59,185,139,0.10)!important;<!-- [et_pb_line_break_holder] -->  border-top:1px solid rgba(59,185,139,0.25)!important;<!-- [et_pb_line_break_holder] -->  color:#3BB98B!important;padding:11px 24px!important;<!-- [et_pb_line_break_holder] -->  font-size:12.5px!important;font-family:'Courier New',monospace!important;<!-- [et_pb_line_break_holder] -->  display:flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-editor-ok svg { width:14px!important;height:14px!important;stroke:#3BB98B!important;fill:none!important;stroke-width:2.5!important;stroke-linecap:round!important;stroke-linejoin:round!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-providers {<!-- [et_pb_line_break_holder] -->  display:flex!important;align-items:center!important;gap:12px!important;<!-- [et_pb_line_break_holder] -->  padding:14px 20px!important;background:#ffffff!important;<!-- [et_pb_line_break_holder] -->  border-top:1px solid #e8ecf0!important;flex-wrap:wrap!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-providers img { width:20px!important;height:20px!important; }<!-- [et_pb_line_break_holder] -->#upl-hero-pyapi .hpy-prov-label { font-size:0.72rem!important;color:#94a3b8!important;font-weight:500!important; }<!-- [et_pb_line_break_holder] -->@media(max-width:900px){<!-- [et_pb_line_break_holder] -->  #upl-hero-pyapi {padding:50px 20px 60px!important;}<!-- [et_pb_line_break_holder] -->  #upl-hero-pyapi .hpy-inner {grid-template-columns:1fr!important;gap:44px!important;}<!-- [et_pb_line_break_holder] -->  #upl-hero-pyapi .hpy-h1 {font-size:34px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->@media(max-width:600px){<!-- [et_pb_line_break_holder] -->  #upl-hero-pyapi {padding:40px 16px 50px!important;}<!-- [et_pb_line_break_holder] -->  #upl-hero-pyapi .hpy-h1 {font-size:28px!important;}<!-- [et_pb_line_break_holder] -->  #upl-hero-pyapi .hpy-actions {flex-direction:column!important;width:100%!important;}<!-- [et_pb_line_break_holder] -->  #upl-hero-pyapi .hpy-cta-primary, #upl-hero-pyapi .hpy-cta-secondary {width:100%!important;justify-content:center!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->@media(max-width:400px){#upl-hero-pyapi .hpy-h1 {font-size:26px!important;}}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><\/style><!-- [et_pb_line_break_holder] --><div id=\"upl-hero-pyapi\"><!-- [et_pb_line_break_holder] -->  <div class=\"hpy-inner\"><!-- [et_pb_line_break_holder] -->    <div class=\"hpy-content\"><!-- [et_pb_line_break_holder] -->      <div class=\"hpy-eyebrow\"><span class=\"hpy-dot\"><\/span><span>Python Tutorial<\/span><\/div><!-- [et_pb_line_break_holder] -->      <h1 class=\"hpy-h1\">How to <span class=\"hpy-accent\">Send Email via API<\/span> in Python (Quick Tutorial)<\/h1><!-- [et_pb_line_break_holder] -->      <pee class=\"hpy-desc\">Skip the SMTP boilerplate. This guide shows you how to use the <a href=\"https:\/\/www.unipile.com\/send-email-api\/\" target=\"_self\">Unipile unified email API<\/a> to send email in Python &#8211; with copy-paste examples for Gmail, Outlook, and IMAP using the <code style=\"font-family:'Courier New',monospace;background:rgba(59,185,139,0.1);padding:1px 5px;border-radius:3px;font-size:15px;color:#0f2736;\">requests<\/code> library.<\/pee><!-- [et_pb_line_break_holder] -->      <!-- [et_pb_line_break_holder] -->      <div class=\"hpy-tags\"><!-- [et_pb_line_break_holder] -->        <span class=\"hpy-tag\">email api python<\/span><!-- [et_pb_line_break_holder] -->        <span class=\"hpy-tag\">send email api python<\/span><!-- [et_pb_line_break_holder] -->        <span class=\"hpy-tag\">Gmail \/ Outlook \/ IMAP<\/span><!-- [et_pb_line_break_holder] -->        <span class=\"hpy-tag\">requests \/ aiohttp<\/span><!-- [et_pb_line_break_holder] -->        <span class=\"hpy-tag\">Flask \/ Django \/ FastAPI<\/span><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"hpy-actions\"><!-- [et_pb_line_break_holder] -->        <a href=\"https:\/\/dashboard.unipile.com\/signup\/\" target=\"_blank\" class=\"hpy-cta-primary\" data-upl-link=\"https:\/\/dashboard.unipile.com\/signup\/\"><svg viewBox=\"0 0 24 24\"><path d=\"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4\"\/><polyline points=\"10 17 15 12 10 7\"\/><line x1=\"15\" y1=\"12\" x2=\"3\" y2=\"12\"\/><\/svg><span>Get your free API key<\/span><\/a><!-- [et_pb_line_break_holder] -->        <a href=\"\/email-api-guide\/\" target=\"_self\" class=\"hpy-cta-secondary\" data-upl-link=\"\/email-api-guide\/\"><svg viewBox=\"0 0 24 24\"><path d=\"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z\"\/><path d=\"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z\"\/><\/svg><span>Read the Email API guide<\/span><\/a><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->    <div class=\"hpy-editor\"><!-- [et_pb_line_break_holder] -->      <div class=\"hpy-editor-bar\"><!-- [et_pb_line_break_holder] -->        <span class=\"hpy-dot-r\"><\/span><span class=\"hpy-dot-y\"><\/span><span class=\"hpy-dot-g\"><\/span><!-- [et_pb_line_break_holder] -->        <span class=\"hpy-filename\">send_email.py<\/span><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"hpy-pre\"><code><span class=\"hpy-k\">import<\/span><span class=\"hpy-w\"> requests, os<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"hpy-n\">API_KEY<\/span><span class=\"hpy-w\">    = os.environ[<\/span><span class=\"hpy-s\">'UNIPILE_API_KEY'<\/span><span class=\"hpy-w\">]<\/span><!-- [et_pb_line_break_holder] --><span class=\"hpy-n\">DSN<\/span><span class=\"hpy-w\">        = os.environ[<\/span><span class=\"hpy-s\">'UNIPILE_DSN'<\/span><span class=\"hpy-w\">]<\/span><!-- [et_pb_line_break_holder] --><span class=\"hpy-n\">ACCOUNT_ID<\/span><span class=\"hpy-w\"> = os.environ[<\/span><span class=\"hpy-s\">'UNIPILE_ACCOUNT_ID'<\/span><span class=\"hpy-w\">]<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"hpy-w\">response = requests.<\/span><span class=\"hpy-fn\">post<\/span><span class=\"hpy-w\">(<\/span><!-- [et_pb_line_break_holder] --><span class=\"hpy-w\">    <\/span><span class=\"hpy-fn\">f<\/span><span class=\"hpy-s\">'{DSN}\/api\/v1\/emails'<\/span><span class=\"hpy-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"hpy-w\">    headers={<\/span><span class=\"hpy-s\">'X-API-KEY'<\/span><span class=\"hpy-w\">: <\/span><span class=\"hpy-n\">API_KEY<\/span><span class=\"hpy-w\">},<\/span><!-- [et_pb_line_break_holder] --><span class=\"hpy-w\">    data={<\/span><!-- [et_pb_line_break_holder] --><span class=\"hpy-w\">        <\/span><span class=\"hpy-s\">'account_id'<\/span><span class=\"hpy-w\">: <\/span><span class=\"hpy-n\">ACCOUNT_ID<\/span><span class=\"hpy-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"hpy-w\">        <\/span><span class=\"hpy-s\">'to'<\/span><span class=\"hpy-w\">: <\/span><span class=\"hpy-s\">'[{\"display_name\":\"Alice\",\"identifier\":\"alice@acme.com\"}]'<\/span><span class=\"hpy-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"hpy-w\">        <\/span><span class=\"hpy-s\">'subject'<\/span><span class=\"hpy-w\">: <\/span><span class=\"hpy-s\">'Hello from Python'<\/span><span class=\"hpy-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"hpy-w\">        <\/span><span class=\"hpy-s\">'body'<\/span><span class=\"hpy-w\">:    <\/span><span class=\"hpy-s\">'<pee>Sent via Unipile!<\/pee>'<\/span><!-- [et_pb_line_break_holder] --><span class=\"hpy-w\">    }<\/span><!-- [et_pb_line_break_holder] --><span class=\"hpy-w\">)<\/span><!-- [et_pb_line_break_holder] --><span class=\"hpy-fn\">print<\/span><span class=\"hpy-w\">(response.<\/span><span class=\"hpy-fn\">json<\/span><span class=\"hpy-w\">())<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->      <div class=\"hpy-editor-ok\"><!-- [et_pb_line_break_holder] -->        <svg viewBox=\"0 0 24 24\"><polyline points=\"20 6 9 17 4 12\"\/><\/svg><!-- [et_pb_line_break_holder] -->        <span>Email delivered &#8211; 202 Accepted<\/span><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"hpy-providers\"><!-- [et_pb_line_break_holder] -->        <span class=\"hpy-prov-label\">Works with:<\/span><!-- [et_pb_line_break_holder] -->        <img decoding=\"async\" src=\"https:\/\/www.unipile.com\/wp-content\/uploads\/2024\/02\/gmail-3.svg\" alt=\"Gmail\"><!-- [et_pb_line_break_holder] -->        <img decoding=\"async\" src=\"https:\/\/www.unipile.com\/wp-content\/uploads\/2024\/02\/outlook-2.svg\" alt=\"Outlook\"><!-- [et_pb_line_break_holder] -->        <img decoding=\"async\" src=\"https:\/\/www.unipile.com\/wp-content\/uploads\/2024\/02\/imap-1.svg\" alt=\"IMAP\"><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] --><\/div><!-- [et_pb_line_break_holder] --><script><!-- [et_pb_line_break_holder] -->document.querySelectorAll('[data-upl-link]').forEach(function(el){<!-- [et_pb_line_break_holder] -->  el.addEventListener('click',function(e){<!-- [et_pb_line_break_holder] -->    e.preventDefault();<!-- [et_pb_line_break_holder] -->    var url=el.getAttribute('data-upl-link');<!-- [et_pb_line_break_holder] -->    if(url.startsWith('http')){window.open(url,'_blank');}<!-- [et_pb_line_break_holder] -->    else{window.location.href=url;}<!-- [et_pb_line_break_holder] -->  });<!-- [et_pb_line_break_holder] -->});<!-- [et_pb_line_break_holder] --><\/script>[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.27.3&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;0px|0px|0px|0px|false|false&#8221; da_disable_devices=&#8221;off|off|off&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221; da_is_popup=&#8221;off&#8221; da_exit_intent=&#8221;off&#8221; da_has_close=&#8221;on&#8221; da_alt_close=&#8221;off&#8221; da_dark_close=&#8221;off&#8221; da_not_modal=&#8221;on&#8221; da_is_singular=&#8221;off&#8221; da_with_loader=&#8221;off&#8221; da_has_shadow=&#8221;on&#8221;][et_pb_row _builder_version=&#8221;4.27.3&#8243; max_width=&#8221;100%&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_code _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;]<style><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi, #upl-tldr-pyapi *, #upl-tldr-pyapi *::before, #upl-tldr-pyapi *::after {<!-- [et_pb_line_break_holder] -->  margin:0!important;padding:0!important;box-sizing:border-box!important;border:none!important;<!-- [et_pb_line_break_holder] -->  outline:none!important;font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif!important;<!-- [et_pb_line_break_holder] -->  line-height:normal!important;letter-spacing:normal!important;text-transform:none!important;<!-- [et_pb_line_break_holder] -->  text-decoration:none!important;list-style:none!important;background:transparent!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi { padding:72px 20px!important; }<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-inner { max-width:1100px!important;margin:0 auto!important; }<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-eyebrow {<!-- [et_pb_line_break_holder] -->  display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:rgba(59,185,139,0.12)!important;color:#2aaa7e!important;<!-- [et_pb_line_break_holder] -->  padding:6px 14px!important;border-radius:20px!important;<!-- [et_pb_line_break_holder] -->  font-size:12px!important;font-weight:700!important;<!-- [et_pb_line_break_holder] -->  text-transform:uppercase!important;letter-spacing:0.5px!important;<!-- [et_pb_line_break_holder] -->  margin-bottom:16px!important;width:fit-content!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-dot { width:7px!important;height:7px!important;background:#3BB98B!important;border-radius:50%!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-h2 {<!-- [et_pb_line_break_holder] -->  font-family:'Poppins',sans-serif!important;font-size:35px!important;font-weight:700!important;<!-- [et_pb_line_break_holder] -->  color:#0f2736!important;line-height:1.2!important;margin-bottom:14px!important;max-width:800px!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-sub { font-size:17px!important;line-height:1.75!important;color:#383838!important;margin-bottom:36px!important;max-width:100%!important; }<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-sub a { color:#2aaa7e!important;font-weight:600!important;text-decoration:underline!important; }<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-grid { display:grid!important;grid-template-columns:1fr 1fr!important;gap:32px!important;align-items:start!important; }<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-steps { display:flex!important;flex-direction:column!important;gap:16px!important; }<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-step { display:flex!important;gap:16px!important;align-items:flex-start!important; }<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-step-num {<!-- [et_pb_line_break_holder] -->  width:36px!important;height:36px!important;min-width:36px!important;<!-- [et_pb_line_break_holder] -->  border-radius:10px!important;background:rgba(59,185,139,0.12)!important;<!-- [et_pb_line_break_holder] -->  color:#2aaa7e!important;display:flex!important;align-items:center!important;justify-content:center!important;<!-- [et_pb_line_break_holder] -->  font-family:'Poppins',sans-serif!important;font-size:14px!important;font-weight:700!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-step-title { font-size:15px!important;font-weight:600!important;color:#0f2736!important;margin-bottom:3px!important; }<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-step-desc { font-size:14px!important;color:#718096!important;line-height:1.6!important; }<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-editor { border-radius:14px!important;overflow:hidden!important;background:#0d1117!important; }<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-editor-bar { background:#161b22!important;padding:12px 18px!important;display:flex!important;align-items:center!important;gap:8px!important;border-bottom:1px solid rgba(255,255,255,0.06)!important; }<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-dot-r {width:12px!important;height:12px!important;border-radius:50%!important;background:#ff5f57!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-dot-y {width:12px!important;height:12px!important;border-radius:50%!important;background:#febc2e!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-dot-g {width:12px!important;height:12px!important;border-radius:50%!important;background:#28c840!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-fname { color:#8b949e!important;font-size:13px!important;margin-left:6px!important;font-family:'Courier New',monospace!important; }<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-pre { padding:22px 24px!important;font-size:13px!important;line-height:1.8!important;overflow-x:auto!important;background:#0d1117!important; }<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-pre code { font-family:'Courier New',monospace!important;white-space:pre!important;display:block!important; }<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .t-c {color:#8b949e!important;}#upl-tldr-pyapi .t-k {color:#ff7b72!important;}#upl-tldr-pyapi .t-fn {color:#d2a8ff!important;}#upl-tldr-pyapi .t-s {color:#a5d6ff!important;}#upl-tldr-pyapi .t-w {color:#e6edf3!important;}#upl-tldr-pyapi .t-n {color:#79c0ff!important;}<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-info-strip {<!-- [et_pb_line_break_holder] -->  background:rgba(59,185,139,0.08)!important;<!-- [et_pb_line_break_holder] -->  border-left:3px solid #3BB98B!important;<!-- [et_pb_line_break_holder] -->  border-radius:0 8px 8px 0!important;<!-- [et_pb_line_break_holder] -->  padding:14px 18px!important;<!-- [et_pb_line_break_holder] -->  margin-top:24px!important;<!-- [et_pb_line_break_holder] -->  font-size:14px!important;<!-- [et_pb_line_break_holder] -->  color:#0f2736!important;<!-- [et_pb_line_break_holder] -->  line-height:1.6!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-tldr-pyapi .tldr-info-strip a { color:#2aaa7e!important;font-weight:600!important;text-decoration:underline!important; }<!-- [et_pb_line_break_holder] -->@media(max-width:900px){<!-- [et_pb_line_break_holder] -->  #upl-tldr-pyapi {padding:50px 20px!important;}<!-- [et_pb_line_break_holder] -->  #upl-tldr-pyapi .tldr-grid {grid-template-columns:1fr!important;gap:28px!important;}<!-- [et_pb_line_break_holder] -->  #upl-tldr-pyapi .tldr-h2 {font-size:28px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->@media(max-width:600px){<!-- [et_pb_line_break_holder] -->  #upl-tldr-pyapi {padding:40px 16px!important;}<!-- [et_pb_line_break_holder] -->  #upl-tldr-pyapi .tldr-h2 {font-size:26px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><\/style><!-- [et_pb_line_break_holder] --><div id=\"upl-tldr-pyapi\"><!-- [et_pb_line_break_holder] -->  <span id=\"anchor-tldr\"><\/span><!-- [et_pb_line_break_holder] -->  <div class=\"tldr-inner\"><!-- [et_pb_line_break_holder] -->    <div class=\"tldr-eyebrow\"><span class=\"tldr-dot\"><\/span><span>TL;DR<\/span><\/div><!-- [et_pb_line_break_holder] -->    <h2 class=\"tldr-h2\">5-Line Python Example<\/h2><!-- [et_pb_line_break_holder] -->    <pee class=\"tldr-sub\">If you already know <a href=\"https:\/\/www.unipile.com\/send-email-api\/\">what a Send Email API is<\/a> and just want the email api python code that actually runs, here it is. The full tutorial follows below.<\/pee><!-- [et_pb_line_break_holder] -->    <div class=\"tldr-grid\"><!-- [et_pb_line_break_holder] -->      <div class=\"tldr-steps\"><!-- [et_pb_line_break_holder] -->        <div class=\"tldr-step\"><!-- [et_pb_line_break_holder] -->          <div class=\"tldr-step-num\">1<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"tldr-step-body\"><!-- [et_pb_line_break_holder] -->            <div class=\"tldr-step-title\">Install requests<\/div><!-- [et_pb_line_break_holder] -->            <div class=\"tldr-step-desc\"><code style=\"font-family:'Courier New',monospace;background:#f4f5f7;padding:2px 6px;border-radius:4px;font-size:13px;color:#0f2736;\">pip install requests python-dotenv<\/code><\/div><!-- [et_pb_line_break_holder] -->          <\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"tldr-step\"><!-- [et_pb_line_break_holder] -->          <div class=\"tldr-step-num\">2<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"tldr-step-body\"><!-- [et_pb_line_break_holder] -->            <div class=\"tldr-step-title\">Set env vars<\/div><!-- [et_pb_line_break_holder] -->            <div class=\"tldr-step-desc\">Add <code style=\"font-family:'Courier New',monospace;background:#f4f5f7;padding:2px 6px;border-radius:4px;font-size:13px;color:#0f2736;\">UNIPILE_DSN<\/code>, <code style=\"font-family:'Courier New',monospace;background:#f4f5f7;padding:2px 6px;border-radius:4px;font-size:13px;color:#0f2736;\">UNIPILE_API_KEY<\/code>, and <code style=\"font-family:'Courier New',monospace;background:#f4f5f7;padding:2px 6px;border-radius:4px;font-size:13px;color:#0f2736;\">UNIPILE_ACCOUNT_ID<\/code> to your <code style=\"font-family:'Courier New',monospace;background:#f4f5f7;padding:2px 6px;border-radius:4px;font-size:13px;color:#0f2736;\">.env<\/code> file.<\/div><!-- [et_pb_line_break_holder] -->          <\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"tldr-step\"><!-- [et_pb_line_break_holder] -->          <div class=\"tldr-step-num\">3<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"tldr-step-body\"><!-- [et_pb_line_break_holder] -->            <div class=\"tldr-step-title\">Link an email account<\/div><!-- [et_pb_line_break_holder] -->            <div class=\"tldr-step-desc\">OAuth for Gmail\/Outlook or SMTP credentials for any IMAP server. One API call &#8211; you only do this once per account.<\/div><!-- [et_pb_line_break_holder] -->          <\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"tldr-step\"><!-- [et_pb_line_break_holder] -->          <div class=\"tldr-step-num\">4<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"tldr-step-body\"><!-- [et_pb_line_break_holder] -->            <div class=\"tldr-step-title\">POST to <code style=\"font-family:'Courier New',monospace;background:#f4f5f7;padding:2px 6px;border-radius:4px;font-size:13px;color:#0f2736;\">\/api\/v1\/emails<\/code><\/div><!-- [et_pb_line_break_holder] -->            <div class=\"tldr-step-desc\">Pass <code style=\"font-family:'Courier New',monospace;background:#f4f5f7;padding:2px 6px;border-radius:4px;font-size:13px;color:#0f2736;\">account_id<\/code>, <code style=\"font-family:'Courier New',monospace;background:#f4f5f7;padding:2px 6px;border-radius:4px;font-size:13px;color:#0f2736;\">to<\/code>, <code style=\"font-family:'Courier New',monospace;background:#f4f5f7;padding:2px 6px;border-radius:4px;font-size:13px;color:#0f2736;\">subject<\/code>, and <code style=\"font-family:'Courier New',monospace;background:#f4f5f7;padding:2px 6px;border-radius:4px;font-size:13px;color:#0f2736;\">body<\/code>. Done.<\/div><!-- [et_pb_line_break_holder] -->          <\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"tldr-info-strip\"><!-- [et_pb_line_break_holder] -->          The same Python code works for Gmail, Outlook, and any IMAP server &#8211; no provider-specific logic needed. Check the <a href=\"\/email-api-guide\/\">Email API guide<\/a> for the full concept overview.<!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"tldr-editor\"><!-- [et_pb_line_break_holder] -->        <div class=\"tldr-editor-bar\"><!-- [et_pb_line_break_holder] -->          <span class=\"tldr-dot-r\"><\/span><span class=\"tldr-dot-y\"><\/span><span class=\"tldr-dot-g\"><\/span><!-- [et_pb_line_break_holder] -->          <span class=\"tldr-fname\">send_email.py<\/span><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"tldr-pre\"><code><span class=\"t-k\">import<\/span><span class=\"t-w\"> requests, os<\/span><!-- [et_pb_line_break_holder] --><span class=\"t-k\">from<\/span><span class=\"t-w\"> dotenv <\/span><span class=\"t-k\">import<\/span><span class=\"t-w\"> load_dotenv<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"t-fn\">load_dotenv<\/span><span class=\"t-w\">()<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"t-n\">API_KEY<\/span><span class=\"t-w\">    = os.environ[<\/span><span class=\"t-s\">'UNIPILE_API_KEY'<\/span><span class=\"t-w\">]<\/span><!-- [et_pb_line_break_holder] --><span class=\"t-n\">DSN<\/span><span class=\"t-w\">        = os.environ[<\/span><span class=\"t-s\">'UNIPILE_DSN'<\/span><span class=\"t-w\">]<\/span><!-- [et_pb_line_break_holder] --><span class=\"t-n\">ACCOUNT_ID<\/span><span class=\"t-w\"> = os.environ[<\/span><span class=\"t-s\">'UNIPILE_ACCOUNT_ID'<\/span><span class=\"t-w\">]<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"t-w\">resp = requests.<\/span><span class=\"t-fn\">post<\/span><span class=\"t-w\">(<\/span><!-- [et_pb_line_break_holder] --><span class=\"t-w\">    <\/span><span class=\"t-fn\">f<\/span><span class=\"t-s\">'{DSN}\/api\/v1\/emails'<\/span><span class=\"t-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"t-w\">    headers={<\/span><span class=\"t-s\">'X-API-KEY'<\/span><span class=\"t-w\">: <\/span><span class=\"t-n\">API_KEY<\/span><span class=\"t-w\">},<\/span><!-- [et_pb_line_break_holder] --><span class=\"t-w\">    data={<\/span><!-- [et_pb_line_break_holder] --><span class=\"t-w\">        <\/span><span class=\"t-s\">'account_id'<\/span><span class=\"t-w\">: <\/span><span class=\"t-n\">ACCOUNT_ID<\/span><span class=\"t-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"t-w\">        <\/span><span class=\"t-s\">'to'<\/span><span class=\"t-w\">: <\/span><span class=\"t-s\">'[{\"display_name\":\"Alice\",\"identifier\":\"alice@acme.com\"}]'<\/span><span class=\"t-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"t-w\">        <\/span><span class=\"t-s\">'subject'<\/span><span class=\"t-w\">: <\/span><span class=\"t-s\">'Hello from Python'<\/span><span class=\"t-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"t-w\">        <\/span><span class=\"t-s\">'body'<\/span><span class=\"t-w\">:    <\/span><span class=\"t-s\">'<pee>Sent via Unipile!<\/pee>'<\/span><!-- [et_pb_line_break_holder] --><span class=\"t-w\">    }<\/span><!-- [et_pb_line_break_holder] --><span class=\"t-w\">)<\/span><!-- [et_pb_line_break_holder] --><span class=\"t-fn\">print<\/span><span class=\"t-w\">(resp.<\/span><span class=\"t-fn\">json<\/span><span class=\"t-w\">()) <\/span><span class=\"t-c\"># {'tracking_id': 'msg_...'}<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] --><\/div>[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.27.3&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;0px|0px|0px|0px|false|false&#8221; da_disable_devices=&#8221;off|off|off&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221; da_is_popup=&#8221;off&#8221; da_exit_intent=&#8221;off&#8221; da_has_close=&#8221;on&#8221; da_alt_close=&#8221;off&#8221; da_dark_close=&#8221;off&#8221; da_not_modal=&#8221;on&#8221; da_is_singular=&#8221;off&#8221; da_with_loader=&#8221;off&#8221; da_has_shadow=&#8221;on&#8221;][et_pb_row _builder_version=&#8221;4.27.3&#8243; max_width=&#8221;100%&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_code _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;]<style><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi, #upl-prereqs-pyapi *, #upl-prereqs-pyapi *::before, #upl-prereqs-pyapi *::after {<!-- [et_pb_line_break_holder] -->  margin:0!important;padding:0!important;box-sizing:border-box!important;border:none!important;<!-- [et_pb_line_break_holder] -->  outline:none!important;font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif!important;<!-- [et_pb_line_break_holder] -->  line-height:normal!important;letter-spacing:normal!important;text-transform:none!important;<!-- [et_pb_line_break_holder] -->  text-decoration:none!important;list-style:none!important;background:transparent!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi { padding:72px 20px!important;background:#f4f5f7!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-inner { max-width:1100px!important;margin:0 auto!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-eyebrow {<!-- [et_pb_line_break_holder] -->  display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:rgba(221,223,76,0.18)!important;color:#8a8c2e!important;<!-- [et_pb_line_break_holder] -->  padding:6px 14px!important;border-radius:20px!important;<!-- [et_pb_line_break_holder] -->  font-size:12px!important;font-weight:700!important;<!-- [et_pb_line_break_holder] -->  text-transform:uppercase!important;letter-spacing:0.5px!important;<!-- [et_pb_line_break_holder] -->  margin-bottom:16px!important;width:fit-content!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-dot { width:7px!important;height:7px!important;background:#DDDF4C!important;border-radius:50%!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-h2 { font-family:'Poppins',sans-serif!important;font-size:35px!important;font-weight:700!important;color:#0f2736!important;line-height:1.2!important;margin-bottom:14px!important;max-width:800px!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-sub { font-size:17px!important;line-height:1.75!important;color:#383838!important;margin-bottom:40px!important;max-width:100%!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-grid { display:grid!important;grid-template-columns:1fr 1fr!important;gap:24px!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-card { background:#ffffff!important;border:1px solid #e5e7eb!important;border-radius:16px!important;padding:28px!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-card-icon { width:44px!important;height:44px!important;border-radius:12px!important;background:rgba(59,185,139,0.12)!important;display:flex!important;align-items:center!important;justify-content:center!important;margin-bottom:16px!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-card-icon svg { width:22px!important;height:22px!important;stroke:#3BB98B!important;fill:none!important;stroke-width:2!important;stroke-linecap:round!important;stroke-linejoin:round!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-card-title { font-family:'Poppins',sans-serif!important;font-size:17px!important;font-weight:700!important;color:#0f2736!important;margin-bottom:10px!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-card-body { font-size:15px!important;line-height:1.7!important;color:#383838!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-card-body code { font-family:'Courier New',monospace!important;background:#f4f5f7!important;padding:2px 6px!important;border-radius:4px!important;font-size:13px!important;color:#0f2736!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-install { margin-top:32px!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-install-title { font-family:'Poppins',sans-serif!important;font-size:20px!important;font-weight:700!important;color:#0f2736!important;margin-bottom:20px!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-tabs { display:flex!important;gap:4px!important;margin-bottom:0!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-tab { padding:8px 16px!important;border-radius:8px 8px 0 0!important;background:#e5e7eb!important;color:#64748b!important;font-size:13px!important;font-weight:600!important;cursor:pointer!important;transition:all 0.2s!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-tab.active { background:#0d1117!important;color:#e6edf3!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-editor { border-radius:0 8px 8px 8px!important;overflow:hidden!important;background:#0d1117!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-pane { display:none!important;padding:20px 24px!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-pane.active { display:block!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-pane code { font-family:'Courier New',monospace!important;white-space:pre!important;display:block!important;font-size:13px!important;line-height:1.8!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .p-c {color:#8b949e!important;}#upl-prereqs-pyapi .p-k {color:#ff7b72!important;}#upl-prereqs-pyapi .p-fn {color:#d2a8ff!important;}#upl-prereqs-pyapi .p-s {color:#a5d6ff!important;}#upl-prereqs-pyapi .p-w {color:#e6edf3!important;}#upl-prereqs-pyapi .p-n {color:#79c0ff!important;}<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-env-card { background:#0d1117!important;border-radius:14px!important;overflow:hidden!important;margin-top:24px!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-env-bar { background:#161b22!important;padding:12px 18px!important;display:flex!important;align-items:center!important;gap:8px!important;border-bottom:1px solid rgba(255,255,255,0.06)!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .p-dot-r {width:12px!important;height:12px!important;border-radius:50%!important;background:#ff5f57!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .p-dot-y {width:12px!important;height:12px!important;border-radius:50%!important;background:#febc2e!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .p-dot-g {width:12px!important;height:12px!important;border-radius:50%!important;background:#28c840!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-fname { color:#8b949e!important;font-size:13px!important;margin-left:6px!important;font-family:'Courier New',monospace!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-env-pre { padding:20px 24px!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-env-pre code { font-family:'Courier New',monospace!important;white-space:pre!important;display:block!important;font-size:13px!important;line-height:1.8!important; }<!-- [et_pb_line_break_holder] -->#upl-prereqs-pyapi .pre-note { margin-top:12px!important;font-size:13px!important;color:#718096!important;line-height:1.6!important; }<!-- [et_pb_line_break_holder] -->@media(max-width:900px){<!-- [et_pb_line_break_holder] -->  #upl-prereqs-pyapi {padding:50px 20px!important;}<!-- [et_pb_line_break_holder] -->  #upl-prereqs-pyapi .pre-grid {grid-template-columns:1fr!important;}<!-- [et_pb_line_break_holder] -->  #upl-prereqs-pyapi .pre-h2 {font-size:28px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->@media(max-width:600px){<!-- [et_pb_line_break_holder] -->  #upl-prereqs-pyapi {padding:40px 16px!important;}<!-- [et_pb_line_break_holder] -->  #upl-prereqs-pyapi .pre-h2 {font-size:26px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><\/style><!-- [et_pb_line_break_holder] --><div id=\"upl-prereqs-pyapi\"><!-- [et_pb_line_break_holder] -->  <span id=\"anchor-prereqs\"><\/span><!-- [et_pb_line_break_holder] -->  <div class=\"pre-inner\"><!-- [et_pb_line_break_holder] -->    <div class=\"pre-eyebrow\"><span class=\"pre-dot\"><\/span><span>Setup<\/span><\/div><!-- [et_pb_line_break_holder] -->    <h2 class=\"pre-h2\">Prerequisites &#038; Setup<\/h2><!-- [et_pb_line_break_holder] -->    <pee class=\"pre-sub\">Before you can use the email API Python workflow in production, you need four things: Python 3.9+, the <code style=\"font-family:'Courier New',monospace;background:rgba(0,0,0,0.06);padding:1px 5px;border-radius:3px;font-size:15px;\">requests<\/code> library, an API key with DSN, and a linked email account.<\/pee><!-- [et_pb_line_break_holder] -->    <div class=\"pre-grid\"><!-- [et_pb_line_break_holder] -->      <div class=\"pre-card\"><!-- [et_pb_line_break_holder] -->        <div class=\"pre-card-icon\"><svg viewBox=\"0 0 24 24\"><polyline points=\"16 18 22 12 16 6\"\/><polyline points=\"8 6 2 12 8 18\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"pre-card-title\">Python 3.9+ (3.11 recommended)<\/div><!-- [et_pb_line_break_holder] -->        <div class=\"pre-card-body\">All examples use f-strings, <code>|<\/code> union types, and standard-library features from 3.9+. Python 3.11 LTS is recommended for production. Check your version with <code>python --version<\/code>.<\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"pre-card\"><!-- [et_pb_line_break_holder] -->        <div class=\"pre-card-icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"pre-card-title\">Unipile API Key &#038; DSN<\/div><!-- [et_pb_line_break_holder] -->        <div class=\"pre-card-body\">Sign up at the Unipile dashboard to get your access token and DSN (a personal HTTPS endpoint like <code>api4.unipile.com:13444<\/code>). Both are required in every request header.<\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"pre-card\"><!-- [et_pb_line_break_holder] -->        <div class=\"pre-card-icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"\/><polyline points=\"14 2 14 8 20 8\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"pre-card-title\">Virtual environment<\/div><!-- [et_pb_line_break_holder] -->        <div class=\"pre-card-body\">Always use a venv to isolate dependencies: <code>python -m venv .venv && source .venv\/bin\/activate<\/code>. Never install packages in the system Python &#8211; this is especially important for credential handling.<\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"pre-card\"><!-- [et_pb_line_break_holder] -->        <div class=\"pre-card-icon\"><svg viewBox=\"0 0 24 24\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"\/><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"pre-card-title\">A linked email account<\/div><!-- [et_pb_line_break_holder] -->        <div class=\"pre-card-body\">You send email <em>through<\/em> a linked account (Gmail, Outlook, or IMAP). The next section walks you through the OAuth flow to link one. You only do this once per account.<\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->    <div class=\"pre-install\"><!-- [et_pb_line_break_holder] -->      <div class=\"pre-install-title\">Installing dependencies<\/div><!-- [et_pb_line_break_holder] -->      <div class=\"pre-tabs\"><!-- [et_pb_line_break_holder] -->        <div class=\"pre-tab active\" onclick=\"switchTabPy(this,'pip')\"><span>pip<\/span><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"pre-tab\" onclick=\"switchTabPy(this,'pipenv')\"><span>pipenv<\/span><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"pre-tab\" onclick=\"switchTabPy(this,'poetry')\"><span>poetry<\/span><\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"pre-editor\"><!-- [et_pb_line_break_holder] -->        <div id=\"pre-pane-pip\" class=\"pre-pane active\"><code><span class=\"p-w\">pip install requests python-dotenv<\/span><!-- [et_pb_line_break_holder] --><span class=\"p-c\"># Optional: async support<\/span><!-- [et_pb_line_break_holder] --><span class=\"p-w\">pip install aiohttp httpx<!-- [et_pb_line_break_holder] --><\/span><span class=\"p-c\"># Optional: retry logic<\/span><!-- [et_pb_line_break_holder] --><span class=\"p-w\">pip install tenacity<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->        <div id=\"pre-pane-pipenv\" class=\"pre-pane\"><code><span class=\"p-w\">pipenv install requests python-dotenv tenacity<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->        <div id=\"pre-pane-poetry\" class=\"pre-pane\"><code><span class=\"p-w\">poetry add requests python-dotenv tenacity<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->    <div class=\"pre-env-card\"><!-- [et_pb_line_break_holder] -->      <div class=\"pre-env-bar\"><!-- [et_pb_line_break_holder] -->        <span class=\"p-dot-r\"><\/span><span class=\"p-dot-y\"><\/span><span class=\"p-dot-g\"><\/span><!-- [et_pb_line_break_holder] -->        <span class=\"pre-fname\">.env<\/span><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"pre-env-pre\"><code><span class=\"p-c\"># Unipile credentials - never commit this file<\/span><span class=\"p-w\"><!-- [et_pb_line_break_holder] --><\/span><span class=\"p-n\">UNIPILE_DSN<\/span><span class=\"p-w\">=https:\/\/api4.unipile.com:13444<!-- [et_pb_line_break_holder] --><\/span><span class=\"p-n\">UNIPILE_API_KEY<\/span><span class=\"p-w\">=your_access_token_here<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><\/span><span class=\"p-c\"># The account ID of the linked email account<\/span><span class=\"p-w\"><!-- [et_pb_line_break_holder] --><\/span><span class=\"p-n\">UNIPILE_ACCOUNT_ID<\/span><span class=\"p-w\">=acc_xxxxxxxxxxxxxxxx<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->    <pee class=\"pre-note\">Add <code style=\"font-family:'Courier New',monospace;background:#f4f5f7;padding:2px 6px;border-radius:4px;font-size:12px;color:#0f2736;\">.env<\/code> to your <code style=\"font-family:'Courier New',monospace;background:#f4f5f7;padding:2px 6px;border-radius:4px;font-size:12px;color:#0f2736;\">.gitignore<\/code>. Load with <code style=\"font-family:'Courier New',monospace;background:#f4f5f7;padding:2px 6px;border-radius:4px;font-size:12px;color:#0f2736;\">python-dotenv<\/code> via <code style=\"font-family:'Courier New',monospace;background:#f4f5f7;padding:2px 6px;border-radius:4px;font-size:12px;color:#0f2736;\">load_dotenv()<\/code> at the top of your script. In production, prefer actual environment variables injected by your deployment platform (Heroku, Railway, Docker Compose).<\/pee><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] --><\/div><!-- [et_pb_line_break_holder] --><script><!-- [et_pb_line_break_holder] -->function switchTabPy(el, id) {<!-- [et_pb_line_break_holder] -->  el.closest('.pre-install').querySelectorAll('.pre-tab').forEach(function(t){ t.classList.remove('active'); });<!-- [et_pb_line_break_holder] -->  el.classList.add('active');<!-- [et_pb_line_break_holder] -->  document.getElementById('pre-pane-' + id).closest('.pre-editor').querySelectorAll('.pre-pane').forEach(function(p){ p.classList.remove('active'); });<!-- [et_pb_line_break_holder] -->  document.getElementById('pre-pane-' + id).classList.add('active');<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><\/script>[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.27.4&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;0px||0px||false|false&#8221; da_disable_devices=&#8221;off|off|off&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221; da_is_popup=&#8221;off&#8221; da_exit_intent=&#8221;off&#8221; da_has_close=&#8221;on&#8221; da_alt_close=&#8221;off&#8221; da_dark_close=&#8221;off&#8221; da_not_modal=&#8221;on&#8221; da_is_singular=&#8221;off&#8221; da_with_loader=&#8221;off&#8221; da_has_shadow=&#8221;on&#8221;][et_pb_row _builder_version=&#8221;4.27.4&#8243; max_width=&#8221;100%&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.27.4&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_code _builder_version=&#8221;4.27.4&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;]<style><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->#upl-cta-py-1, #upl-cta-py-1 *, #upl-cta-py-1 *::before, #upl-cta-py-1 *::after {<!-- [et_pb_line_break_holder] -->  margin:0!important;padding:0!important;box-sizing:border-box!important;border:none!important;<!-- [et_pb_line_break_holder] -->  outline:none!important;font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif!important;<!-- [et_pb_line_break_holder] -->  line-height:normal!important;letter-spacing:normal!important;text-transform:none!important;<!-- [et_pb_line_break_holder] -->  text-decoration:none!important;list-style:none!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-cta-py-1 { padding:32px 20px!important;background:#ffffff!important;border-radius:10px; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-1 .cy1-inner { max-width:1100px!important;margin:0 auto!important;display:flex!important;align-items:center!important;justify-content:space-between!important;gap:24px!important;flex-wrap:wrap!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-1 .cy1-left { display:flex!important;align-items:center!important;gap:16px!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-1 .cy1-icon { width:44px!important;height:44px!important;min-width:44px!important;border-radius:12px!important;background:rgba(59,185,139,0.12)!important;display:flex!important;align-items:center!important;justify-content:center!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-1 .cy1-icon svg { width:20px!important;height:20px!important;stroke:#3BB98B!important;fill:none!important;stroke-width:2!important;stroke-linecap:round!important;stroke-linejoin:round!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-1 .cy1-text-title { font-family:'Poppins',sans-serif!important;font-size:16px!important;font-weight:700!important;color:#0f2736!important;line-height:1.3!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-1 .cy1-text-desc { font-size:14px!important;color:#64748b!important;line-height:1.5!important;margin-top:3px!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-1 .cy1-cta {  display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:#DDDF4C!important;color:#0f2736!important;<!-- [et_pb_line_break_holder] -->  padding:12px 24px!important;border-radius:8px!important;<!-- [et_pb_line_break_holder] -->  font-size:0.9rem!important;font-weight:600!important;<!-- [et_pb_line_break_holder] -->  border:2px solid #DDDF4C!important;<!-- [et_pb_line_break_holder] -->  transition:all 0.3s ease!important;cursor:pointer!important;<!-- [et_pb_line_break_holder] -->  white-space:nowrap!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-cta-py-1 .cy1-cta:hover { transform:translateY(-2px)!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-1 .cy1-cta svg { width:14px!important;height:14px!important;stroke:currentColor!important;fill:none!important;stroke-width:2.5!important;stroke-linecap:round!important;stroke-linejoin:round!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->@media(max-width:700px){<!-- [et_pb_line_break_holder] -->  #upl-cta-py-1 .cy1-inner {flex-direction:column!important;align-items:flex-start!important;}<!-- [et_pb_line_break_holder] -->  #upl-cta-py-1 .cy1-cta {width:100%!important;justify-content:center!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><\/style><!-- [et_pb_line_break_holder] --><div id=\"upl-cta-py-1\"><!-- [et_pb_line_break_holder] -->  <div class=\"cy1-inner\"><!-- [et_pb_line_break_holder] -->    <div class=\"cy1-left\"><!-- [et_pb_line_break_holder] -->      <div class=\"cy1-icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4\"\/><polyline points=\"10 17 15 12 10 7\"\/><line x1=\"15\" y1=\"12\" x2=\"3\" y2=\"12\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->      <div><!-- [et_pb_line_break_holder] -->        <div class=\"cy1-text-title\"><span>Ready to run your first email send?<\/span><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"cy1-text-desc\"><span>Get a free API key &#8211; takes 30 seconds, no credit card required.<\/span><\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->    <a href=\"https:\/\/dashboard.unipile.com\/signup\/\" target=\"_blank\" class=\"cy1-cta\" data-upl-link=\"https:\/\/dashboard.unipile.com\/signup\/\"><svg viewBox=\"0 0 24 24\"><path d=\"M5 12h14\"\/><path d=\"M12 5l7 7-7 7\"\/><\/svg><span>Get your free API key<\/span><\/a><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] --><\/div><!-- [et_pb_line_break_holder] --><script><!-- [et_pb_line_break_holder] -->document.querySelectorAll('#upl-cta-py-1 [data-upl-link]').forEach(function(el){<!-- [et_pb_line_break_holder] -->  el.addEventListener('click',function(e){<!-- [et_pb_line_break_holder] -->    e.preventDefault();<!-- [et_pb_line_break_holder] -->    var url=el.getAttribute('data-upl-link');<!-- [et_pb_line_break_holder] -->    if(url.includes('unipile.com')||url.startsWith('\/')){window.location.href=url;}else if(url.startsWith('http')){window.open(url,'_blank');}else{window.location.href=url;}<!-- [et_pb_line_break_holder] -->  });<!-- [et_pb_line_break_holder] -->});<!-- [et_pb_line_break_holder] --><\/script>[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.27.3&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;0px|0px|0px|0px|false|false&#8221; da_disable_devices=&#8221;off|off|off&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221; da_is_popup=&#8221;off&#8221; da_exit_intent=&#8221;off&#8221; da_has_close=&#8221;on&#8221; da_alt_close=&#8221;off&#8221; da_dark_close=&#8221;off&#8221; da_not_modal=&#8221;on&#8221; da_is_singular=&#8221;off&#8221; da_with_loader=&#8221;off&#8221; da_has_shadow=&#8221;on&#8221;][et_pb_row _builder_version=&#8221;4.27.3&#8243; max_width=&#8221;100%&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_code _builder_version=&#8221;4.27.4&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;]<style><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->#upl-connect-pyapi, #upl-connect-pyapi *, #upl-connect-pyapi *::before, #upl-connect-pyapi *::after {<!-- [et_pb_line_break_holder] -->  margin:0!important;padding:0!important;box-sizing:border-box!important;border:none!important;<!-- [et_pb_line_break_holder] -->  outline:none!important;font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif!important;<!-- [et_pb_line_break_holder] -->  line-height:normal!important;letter-spacing:normal!important;text-transform:none!important;<!-- [et_pb_line_break_holder] -->  text-decoration:none!important;list-style:none!important;background:transparent!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi { padding:72px 20px!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-inner { max-width:1100px!important;margin:0 auto!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-eyebrow {<!-- [et_pb_line_break_holder] -->  display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:rgba(59,185,139,0.12)!important;color:#2aaa7e!important;<!-- [et_pb_line_break_holder] -->  padding:6px 14px!important;border-radius:20px!important;<!-- [et_pb_line_break_holder] -->  font-size:12px!important;font-weight:700!important;<!-- [et_pb_line_break_holder] -->  text-transform:uppercase!important;letter-spacing:0.5px!important;<!-- [et_pb_line_break_holder] -->  margin-bottom:16px!important;width:fit-content!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-dot { width:7px!important;height:7px!important;background:#3BB98B!important;border-radius:50%!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-h2 { font-family:'Poppins',sans-serif!important;font-size:35px!important;font-weight:700!important;color:#0f2736!important;line-height:1.2!important;margin-bottom:14px!important;max-width:820px!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-sub { font-size:17px!important;line-height:1.75!important;color:#383838!important;margin-bottom:12px!important;max-width:100%!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-sub a { color:#2aaa7e!important;font-weight:600!important;text-decoration:underline!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-intro-note { font-size:15px!important;color:#718096!important;line-height:1.7!important;margin-bottom:36px!important;max-width:100%!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-tabs { display:flex!important;gap:8px!important;margin-bottom:0!important;flex-wrap:wrap!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-tab {<!-- [et_pb_line_break_holder] -->  display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  padding:10px 18px!important;border-radius:10px 10px 0 0!important;<!-- [et_pb_line_break_holder] -->  background:#f4f5f7!important;color:#64748b!important;<!-- [et_pb_line_break_holder] -->  font-size:14px!important;font-weight:600!important;cursor:pointer!important;<!-- [et_pb_line_break_holder] -->  border:1px solid #e5e7eb!important;border-bottom:none!important;<!-- [et_pb_line_break_holder] -->  transition:all 0.2s!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-tab img { width:18px!important;height:18px!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-tab.active { background:#0d1117!important;color:#e6edf3!important;border-color:#0d1117!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-editor { border-radius:0 8px 8px 8px!important;overflow:hidden!important;background:#0d1117!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-editor-bar { background:#161b22!important;padding:12px 18px!important;display:flex!important;align-items:center!important;gap:8px!important;border-bottom:1px solid rgba(255,255,255,0.06)!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .c-dot-r {width:12px!important;height:12px!important;border-radius:50%!important;background:#ff5f57!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .c-dot-y {width:12px!important;height:12px!important;border-radius:50%!important;background:#febc2e!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .c-dot-g {width:12px!important;height:12px!important;border-radius:50%!important;background:#28c840!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-fname { color:#8b949e!important;font-size:13px!important;margin-left:6px!important;font-family:'Courier New',monospace!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-pane { display:none!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-pane.active { display:block!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-pre { padding:22px 24px!important;font-size:13px!important;line-height:1.8!important;overflow-x:auto!important;background:#0d1117!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-pre code { font-family:'Courier New',monospace!important;white-space:pre!important;display:block!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .cn-c {color:#8b949e!important;}#upl-connect-pyapi .cn-k {color:#ff7b72!important;}#upl-connect-pyapi .cn-fn {color:#d2a8ff!important;}#upl-connect-pyapi .cn-s {color:#a5d6ff!important;}#upl-connect-pyapi .cn-w {color:#e6edf3!important;}#upl-connect-pyapi .cn-n {color:#79c0ff!important;}<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-info-grid { display:grid!important;grid-template-columns:repeat(3,1fr)!important;gap:20px!important;margin-top:32px!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-info-card { background:#ffffff!important;border-radius:12px!important;padding:20px!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-info-card-head { display:flex!important;align-items:center!important;gap:10px!important;margin-bottom:10px!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-info-card-head img { width:24px!important;height:24px!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-info-card-title { font-family:'Poppins',sans-serif!important;font-size:14px!important;font-weight:700!important;color:#0f2736!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-info-card-body { font-size:13px!important;color:#718096!important;line-height:1.6!important; }<!-- [et_pb_line_break_holder] -->#upl-connect-pyapi .con-info-card-body a { color:#2aaa7e!important;font-weight:600!important;text-decoration:underline!important; }<!-- [et_pb_line_break_holder] -->@media(max-width:900px){<!-- [et_pb_line_break_holder] -->  #upl-connect-pyapi {padding:50px 20px!important;}<!-- [et_pb_line_break_holder] -->  #upl-connect-pyapi .con-info-grid {grid-template-columns:1fr!important;}<!-- [et_pb_line_break_holder] -->  #upl-connect-pyapi .con-h2 {font-size:28px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->@media(max-width:600px){<!-- [et_pb_line_break_holder] -->  #upl-connect-pyapi {padding:40px 16px!important;}<!-- [et_pb_line_break_holder] -->  #upl-connect-pyapi .con-h2 {font-size:26px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><\/style><!-- [et_pb_line_break_holder] --><div id=\"upl-connect-pyapi\"><!-- [et_pb_line_break_holder] -->  <span id=\"anchor-connect\"><\/span><!-- [et_pb_line_break_holder] -->  <div class=\"con-inner\"><!-- [et_pb_line_break_holder] -->    <div class=\"con-eyebrow\"><span class=\"con-dot\"><\/span><span>Account Linking<\/span><\/div><!-- [et_pb_line_break_holder] -->    <h2 class=\"con-h2\">Connecting Your First Email Account<\/h2><!-- [et_pb_line_break_holder] -->    <pee class=\"con-sub\">Before you can send, you need to link an email account to Unipile. This is a one-time step per account. See the full <a href=\"https:\/\/www.unipile.com\/unified-email-api-integration\/\">unified email API integration guide<\/a> for more on multi-account flows.<\/pee><!-- [et_pb_line_break_holder] -->    <pee class=\"con-intro-note\">Unipile uses a hosted auth wizard &#8211; your Python script generates an auth link, the user clicks it and completes OAuth in the browser, then Unipile calls your webhook with the new <code style=\"font-family:'Courier New',monospace;background:#f4f5f7;padding:2px 6px;border-radius:4px;font-size:12px;color:#0f2736;\">account_id<\/code>. No SMTP credentials are stored in your code for Gmail or Outlook.<\/pee><!-- [et_pb_line_break_holder] -->    <div class=\"con-tabs\"><!-- [et_pb_line_break_holder] -->      <div class=\"con-tab active\" onclick=\"switchConTab(this,'gmail')\"><img decoding=\"async\" src=\"https:\/\/www.unipile.com\/wp-content\/uploads\/2024\/02\/gmail-3.svg\" alt=\"Gmail\"><span>Gmail OAuth<\/span><\/div><!-- [et_pb_line_break_holder] -->      <div class=\"con-tab\" onclick=\"switchConTab(this,'outlook')\"><img decoding=\"async\" src=\"https:\/\/www.unipile.com\/wp-content\/uploads\/2024\/02\/outlook-2.svg\" alt=\"Outlook\"><span>Outlook OAuth<\/span><\/div><!-- [et_pb_line_break_holder] -->      <div class=\"con-tab\" onclick=\"switchConTab(this,'imap')\"><img decoding=\"async\" src=\"https:\/\/www.unipile.com\/wp-content\/uploads\/2024\/02\/imap-1.svg\" alt=\"IMAP\"><span>IMAP \/ SMTP<\/span><\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->    <div class=\"con-editor\"><!-- [et_pb_line_break_holder] -->      <div class=\"con-editor-bar\"><!-- [et_pb_line_break_holder] -->        <span class=\"c-dot-r\"><\/span><span class=\"c-dot-y\"><\/span><span class=\"c-dot-g\"><\/span><!-- [et_pb_line_break_holder] -->        <span class=\"con-fname\" id=\"con-fname-label\">connect_gmail.py<\/span><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div id=\"con-pane-gmail\" class=\"con-pane active\"><!-- [et_pb_line_break_holder] -->        <div class=\"con-pre\"><code><span class=\"cn-k\">import<\/span><span class=\"cn-w\"> requests, os<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-k\">from<\/span><span class=\"cn-w\"> dotenv <\/span><span class=\"cn-k\">import<\/span><span class=\"cn-w\"> load_dotenv<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"cn-fn\">load_dotenv<\/span><span class=\"cn-w\">()<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"cn-n\">API_KEY<\/span><span class=\"cn-w\"> = os.environ[<\/span><span class=\"cn-s\">'UNIPILE_API_KEY'<\/span><span class=\"cn-w\">]<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-n\">DSN<\/span><span class=\"cn-w\">     = os.environ[<\/span><span class=\"cn-s\">'UNIPILE_DSN'<\/span><span class=\"cn-w\">]<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"cn-c\"># Step 1: create a hosted auth link for Gmail OAuth<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">resp = requests.<\/span><span class=\"cn-fn\">post<\/span><span class=\"cn-w\">(<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">    <\/span><span class=\"cn-fn\">f<\/span><span class=\"cn-s\">'{DSN}\/api\/v1\/hosted\/accounts\/link'<\/span><span class=\"cn-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">    headers={<\/span><span class=\"cn-s\">'X-API-KEY'<\/span><span class=\"cn-w\">: <\/span><span class=\"cn-n\">API_KEY<\/span><span class=\"cn-w\">},<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">    data={<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">        <\/span><span class=\"cn-s\">'type'<\/span><span class=\"cn-w\">:         <\/span><span class=\"cn-s\">'GOOGLE'<\/span><span class=\"cn-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">        <\/span><span class=\"cn-s\">'name'<\/span><span class=\"cn-w\">:         <\/span><span class=\"cn-s\">'Alice Gmail'<\/span><span class=\"cn-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">        <\/span><span class=\"cn-s\">'success_url'<\/span><span class=\"cn-w\">:   <\/span><span class=\"cn-s\">'https:\/\/yourapp.com\/oauth\/success'<\/span><span class=\"cn-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">        <\/span><span class=\"cn-s\">'failure_url'<\/span><span class=\"cn-w\">:   <\/span><span class=\"cn-s\">'https:\/\/yourapp.com\/oauth\/failure'<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">    }<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">)<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"cn-c\"># Step 2: send this URL to your user<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">auth_url = resp.<\/span><span class=\"cn-fn\">json<\/span><span class=\"cn-w\">()[<\/span><span class=\"cn-s\">'url'<\/span><span class=\"cn-w\">]<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-fn\">print<\/span><span class=\"cn-w\">(<\/span><span class=\"cn-s\">f'Direct user to: {auth_url}'<\/span><span class=\"cn-w\">)<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"cn-c\"># Step 3: Unipile POSTs {account_id} to your webhook after OAuth<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-c\"># See \/gmail-api-send-email-a-comprehensive-guide-for-developers\/ for Gmail details<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div id=\"con-pane-outlook\" class=\"con-pane\"><!-- [et_pb_line_break_holder] -->        <div class=\"con-pre\"><code><span class=\"cn-k\">import<\/span><span class=\"cn-w\"> requests, os<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-k\">from<\/span><span class=\"cn-w\"> dotenv <\/span><span class=\"cn-k\">import<\/span><span class=\"cn-w\"> load_dotenv<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"cn-fn\">load_dotenv<\/span><span class=\"cn-w\">()<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"cn-c\"># Outlook OAuth - covers personal Outlook + Microsoft 365<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-c\"># See \/microsoft-graph-api-email-integration-guide\/<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">resp = requests.<\/span><span class=\"cn-fn\">post<\/span><span class=\"cn-w\">(<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">    <\/span><span class=\"cn-fn\">f<\/span><span class=\"cn-s\">'{os.environ[\"UNIPILE_DSN\"]}\/api\/v1\/hosted\/accounts\/link'<\/span><span class=\"cn-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">    headers={<\/span><span class=\"cn-s\">'X-API-KEY'<\/span><span class=\"cn-w\">: os.environ[<\/span><span class=\"cn-s\">'UNIPILE_API_KEY'<\/span><span class=\"cn-w\">]},<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">    data={<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">        <\/span><span class=\"cn-s\">'type'<\/span><span class=\"cn-w\">:         <\/span><span class=\"cn-s\">'MICROSOFT'<\/span><span class=\"cn-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">        <\/span><span class=\"cn-s\">'name'<\/span><span class=\"cn-w\">:         <\/span><span class=\"cn-s\">'Bob Outlook'<\/span><span class=\"cn-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">        <\/span><span class=\"cn-s\">'success_url'<\/span><span class=\"cn-w\">:   <\/span><span class=\"cn-s\">'https:\/\/yourapp.com\/oauth\/success'<\/span><span class=\"cn-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">        <\/span><span class=\"cn-s\">'failure_url'<\/span><span class=\"cn-w\">:   <\/span><span class=\"cn-s\">'https:\/\/yourapp.com\/oauth\/failure'<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">    }<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">)<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-fn\">print<\/span><span class=\"cn-w\">(resp.<\/span><span class=\"cn-fn\">json<\/span><span class=\"cn-w\">()[<\/span><span class=\"cn-s\">'url'<\/span><span class=\"cn-w\">])<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div id=\"con-pane-imap\" class=\"con-pane\"><!-- [et_pb_line_break_holder] -->        <div class=\"con-pre\"><code><span class=\"cn-k\">import<\/span><span class=\"cn-w\"> requests, os, json<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"cn-c\"># IMAP: pass SMTP\/IMAP credentials directly (no OAuth redirect needed)<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-c\"># See \/the-developers-guide-to-imap-api-solution\/ for full IMAP details<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">resp = requests.<\/span><span class=\"cn-fn\">post<\/span><span class=\"cn-w\">(<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">    <\/span><span class=\"cn-fn\">f<\/span><span class=\"cn-s\">'{os.environ[\"UNIPILE_DSN\"]}\/api\/v1\/accounts'<\/span><span class=\"cn-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">    headers={<\/span><span class=\"cn-s\">'X-API-KEY'<\/span><span class=\"cn-w\">: os.environ[<\/span><span class=\"cn-s\">'UNIPILE_API_KEY'<\/span><span class=\"cn-w\">]},<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">    json={<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">        <\/span><span class=\"cn-s\">'provider'<\/span><span class=\"cn-w\">: <\/span><span class=\"cn-s\">'IMAP'<\/span><span class=\"cn-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">        <\/span><span class=\"cn-s\">'username'<\/span><span class=\"cn-w\">: <\/span><span class=\"cn-s\">'alice@company.com'<\/span><span class=\"cn-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">        <\/span><span class=\"cn-s\">'password'<\/span><span class=\"cn-w\">: <\/span><span class=\"cn-s\">'app_password_here'<\/span><span class=\"cn-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">        <\/span><span class=\"cn-s\">'imap_host'<\/span><span class=\"cn-w\">: <\/span><span class=\"cn-s\">'imap.company.com'<\/span><span class=\"cn-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">        <\/span><span class=\"cn-s\">'smtp_host'<\/span><span class=\"cn-w\">: <\/span><span class=\"cn-s\">'smtp.company.com'<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">    }<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">)<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-w\">account_id = resp.<\/span><span class=\"cn-fn\">json<\/span><span class=\"cn-w\">()[<\/span><span class=\"cn-s\">'account_id'<\/span><span class=\"cn-w\">]<\/span><!-- [et_pb_line_break_holder] --><span class=\"cn-fn\">print<\/span><span class=\"cn-w\">(<\/span><span class=\"cn-s\">f'Linked account: {account_id}'<\/span><span class=\"cn-w\">)<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->    <div class=\"con-info-grid\"><!-- [et_pb_line_break_holder] -->      <div class=\"con-info-card\"><!-- [et_pb_line_break_holder] -->        <div class=\"con-info-card-head\"><!-- [et_pb_line_break_holder] -->          <img decoding=\"async\" src=\"https:\/\/www.unipile.com\/wp-content\/uploads\/2024\/02\/gmail-3.svg\" alt=\"Gmail\"><!-- [et_pb_line_break_holder] -->          <div class=\"con-info-card-title\">Gmail<\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"con-info-card-body\">Uses Google OAuth 2.0. No passwords stored. Token refresh is automatic. See the <a href=\"\/gmail-api-send-email-a-comprehensive-guide-for-developers\/\">Gmail API send email guide<\/a> for scope details.<\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"con-info-card\"><!-- [et_pb_line_break_holder] -->        <div class=\"con-info-card-head\"><!-- [et_pb_line_break_holder] -->          <img decoding=\"async\" src=\"https:\/\/www.unipile.com\/wp-content\/uploads\/2024\/02\/outlook-2.svg\" alt=\"Outlook\"><!-- [et_pb_line_break_holder] -->          <div class=\"con-info-card-title\">Outlook \/ Microsoft 365<\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"con-info-card-body\">Uses Microsoft Graph OAuth. Covers personal Outlook and Microsoft 365 \/ Exchange Online. See the <a href=\"\/microsoft-graph-api-email-integration-guide\/\">Microsoft Graph email guide<\/a> for admin consent flows.<\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"con-info-card\"><!-- [et_pb_line_break_holder] -->        <div class=\"con-info-card-head\"><!-- [et_pb_line_break_holder] -->          <img decoding=\"async\" src=\"https:\/\/www.unipile.com\/wp-content\/uploads\/2024\/02\/imap-1.svg\" alt=\"IMAP\"><!-- [et_pb_line_break_holder] -->          <div class=\"con-info-card-title\">IMAP \/ SMTP<\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"con-info-card-body\">Pass credentials directly. Works with any IMAP server: Zoho, Yahoo, FastMail, custom Exchange. See the <a href=\"\/the-developers-guide-to-imap-api-solution\/\">IMAP API solution guide<\/a> for port configuration.<\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] --><\/div><!-- [et_pb_line_break_holder] --><script><!-- [et_pb_line_break_holder] -->function switchConTab(el, id) {<!-- [et_pb_line_break_holder] -->  document.querySelectorAll('#upl-connect-pyapi .con-tab').forEach(function(t){ t.classList.remove('active'); });<!-- [et_pb_line_break_holder] -->  el.classList.add('active');<!-- [et_pb_line_break_holder] -->  document.querySelectorAll('#upl-connect-pyapi .con-pane').forEach(function(p){ p.classList.remove('active'); });<!-- [et_pb_line_break_holder] -->  document.getElementById('con-pane-' + id).classList.add('active');<!-- [et_pb_line_break_holder] -->  var fnames = {gmail:'connect_gmail.py', outlook:'connect_outlook.py', imap:'connect_imap.py'};<!-- [et_pb_line_break_holder] -->  document.getElementById('con-fname-label').textContent = fnames[id];<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><\/script>[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.27.3&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;0px|0px|0px|0px|false|false&#8221; da_disable_devices=&#8221;off|off|off&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221; da_is_popup=&#8221;off&#8221; da_exit_intent=&#8221;off&#8221; da_has_close=&#8221;on&#8221; da_alt_close=&#8221;off&#8221; da_dark_close=&#8221;off&#8221; da_not_modal=&#8221;on&#8221; da_is_singular=&#8221;off&#8221; da_with_loader=&#8221;off&#8221; da_has_shadow=&#8221;on&#8221;][et_pb_row _builder_version=&#8221;4.27.3&#8243; max_width=&#8221;100%&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_code _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;]<style><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->#upl-send-pyapi, #upl-send-pyapi *, #upl-send-pyapi *::before, #upl-send-pyapi *::after {<!-- [et_pb_line_break_holder] -->  margin:0!important;padding:0!important;box-sizing:border-box!important;border:none!important;<!-- [et_pb_line_break_holder] -->  outline:none!important;font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif!important;<!-- [et_pb_line_break_holder] -->  line-height:normal!important;letter-spacing:normal!important;text-transform:none!important;<!-- [et_pb_line_break_holder] -->  text-decoration:none!important;list-style:none!important;background:transparent!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-send-pyapi { padding:72px 20px!important;background:#f4f5f7!important; }<!-- [et_pb_line_break_holder] -->#upl-send-pyapi .snd-inner { max-width:1100px!important;margin:0 auto!important; }<!-- [et_pb_line_break_holder] -->#upl-send-pyapi .snd-eyebrow {<!-- [et_pb_line_break_holder] -->  display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:rgba(221,223,76,0.18)!important;color:#8a8c2e!important;<!-- [et_pb_line_break_holder] -->  padding:6px 14px!important;border-radius:20px!important;<!-- [et_pb_line_break_holder] -->  font-size:12px!important;font-weight:700!important;<!-- [et_pb_line_break_holder] -->  text-transform:uppercase!important;letter-spacing:0.5px!important;<!-- [et_pb_line_break_holder] -->  margin-bottom:16px!important;width:fit-content!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-send-pyapi .snd-dot { width:7px!important;height:7px!important;background:#DDDF4C!important;border-radius:50%!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->#upl-send-pyapi .snd-h2 { font-family:'Poppins',sans-serif!important;font-size:35px!important;font-weight:700!important;color:#0f2736!important;line-height:1.2!important;margin-bottom:14px!important;max-width:820px!important; }<!-- [et_pb_line_break_holder] -->#upl-send-pyapi .snd-sub { font-size:17px!important;line-height:1.75!important;color:#383838!important;margin-bottom:40px!important;max-width:100%!important; }<!-- [et_pb_line_break_holder] -->#upl-send-pyapi .snd-blocks { display:flex!important;flex-direction:column!important;gap:32px!important; }<!-- [et_pb_line_break_holder] -->#upl-send-pyapi .snd-block { background:#ffffff!important;border:1px solid #e5e7eb!important;border-radius:16px!important;overflow:hidden!important; }<!-- [et_pb_line_break_holder] -->#upl-send-pyapi .snd-block-header { padding:20px 24px!important;border-bottom:1px solid #f0f1f3!important;display:flex!important;align-items:center!important;gap:12px!important; }<!-- [et_pb_line_break_holder] -->#upl-send-pyapi .snd-block-num { width:32px!important;height:32px!important;min-width:32px!important;border-radius:8px!important;background:rgba(59,185,139,0.12)!important;color:#2aaa7e!important;display:flex!important;align-items:center!important;justify-content:center!important;font-family:'Poppins',sans-serif!important;font-size:13px!important;font-weight:700!important; }<!-- [et_pb_line_break_holder] -->#upl-send-pyapi .snd-block-title { font-family:'Poppins',sans-serif!important;font-size:17px!important;font-weight:700!important;color:#0f2736!important; }<!-- [et_pb_line_break_holder] -->#upl-send-pyapi .snd-block-tag { font-size:12px!important;color:#718096!important;margin-left:auto!important;background:#f4f5f7!important;padding:3px 10px!important;border-radius:20px!important; }<!-- [et_pb_line_break_holder] -->#upl-send-pyapi .snd-pre { padding:22px 24px!important;font-size:13px!important;line-height:1.8!important;overflow-x:auto!important;background:#0d1117!important; }<!-- [et_pb_line_break_holder] -->#upl-send-pyapi .snd-pre code { font-family:'Courier New',monospace!important;white-space:pre!important;display:block!important; }<!-- [et_pb_line_break_holder] -->#upl-send-pyapi .s-c {color:#8b949e!important;}#upl-send-pyapi .s-k {color:#ff7b72!important;}#upl-send-pyapi .s-fn {color:#d2a8ff!important;}#upl-send-pyapi .s-s {color:#a5d6ff!important;}#upl-send-pyapi .s-w {color:#e6edf3!important;}#upl-send-pyapi .s-n {color:#79c0ff!important;}<!-- [et_pb_line_break_holder] -->#upl-send-pyapi .snd-block-note { padding:14px 24px!important;background:rgba(59,185,139,0.05)!important;border-top:1px solid rgba(59,185,139,0.15)!important;font-size:13px!important;color:#718096!important;line-height:1.6!important; }<!-- [et_pb_line_break_holder] -->#upl-send-pyapi .snd-block-note strong { color:#0f2736!important; }<!-- [et_pb_line_break_holder] -->@media(max-width:900px){<!-- [et_pb_line_break_holder] -->  #upl-send-pyapi {padding:50px 20px!important;}<!-- [et_pb_line_break_holder] -->  #upl-send-pyapi .snd-h2 {font-size:28px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->@media(max-width:600px){<!-- [et_pb_line_break_holder] -->  #upl-send-pyapi {padding:40px 16px!important;}<!-- [et_pb_line_break_holder] -->  #upl-send-pyapi .snd-h2 {font-size:26px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><\/style><!-- [et_pb_line_break_holder] --><div id=\"upl-send-pyapi\"><!-- [et_pb_line_break_holder] -->  <span id=\"anchor-send\"><\/span><!-- [et_pb_line_break_holder] -->  <div class=\"snd-inner\"><!-- [et_pb_line_break_holder] -->    <div class=\"snd-eyebrow\"><span class=\"snd-dot\"><\/span><span>Core API<\/span><\/div><!-- [et_pb_line_break_holder] -->    <h2 class=\"snd-h2\">Sending Your First Email from Python<\/h2><!-- [et_pb_line_break_holder] -->    <pee class=\"snd-sub\">The send endpoint accepts <code style=\"font-family:'Courier New',monospace;background:rgba(0,0,0,0.06);padding:1px 5px;border-radius:3px;font-size:15px;\">multipart\/form-data<\/code>. Use <code style=\"font-family:'Courier New',monospace;background:rgba(0,0,0,0.06);padding:1px 5px;border-radius:3px;font-size:15px;\">data=<\/code> (not <code style=\"font-family:'Courier New',monospace;background:rgba(0,0,0,0.06);padding:1px 5px;border-radius:3px;font-size:15px;\">json=<\/code>) in <code style=\"font-family:'Courier New',monospace;background:rgba(0,0,0,0.06);padding:1px 5px;border-radius:3px;font-size:15px;\">requests.post()<\/code>. The <code style=\"font-family:'Courier New',monospace;background:rgba(0,0,0,0.06);padding:1px 5px;border-radius:3px;font-size:15px;\">to<\/code>, <code style=\"font-family:'Courier New',monospace;background:rgba(0,0,0,0.06);padding:1px 5px;border-radius:3px;font-size:15px;\">cc<\/code>, and <code style=\"font-family:'Courier New',monospace;background:rgba(0,0,0,0.06);padding:1px 5px;border-radius:3px;font-size:15px;\">bcc<\/code> fields are JSON-encoded strings inside the form data.<\/pee><!-- [et_pb_line_break_holder] -->    <div class=\"snd-blocks\"><!-- [et_pb_line_break_holder] -->      <div class=\"snd-block\"><!-- [et_pb_line_break_holder] -->        <div class=\"snd-block-header\"><!-- [et_pb_line_break_holder] -->          <div class=\"snd-block-num\">1<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"snd-block-title\">Plain text email<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"snd-block-tag\">Basic<\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"snd-pre\"><code><span class=\"s-k\">import<\/span><span class=\"s-w\"> requests, os, json<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"s-w\">requests.<\/span><span class=\"s-fn\">post<\/span><span class=\"s-w\">(<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">    <\/span><span class=\"s-fn\">f<\/span><span class=\"s-s\">'{os.environ[\"UNIPILE_DSN\"]}\/api\/v1\/emails'<\/span><span class=\"s-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">    headers={<\/span><span class=\"s-s\">'X-API-KEY'<\/span><span class=\"s-w\">: os.environ[<\/span><span class=\"s-s\">'UNIPILE_API_KEY'<\/span><span class=\"s-w\">]},<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">    data={<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">        <\/span><span class=\"s-s\">'account_id'<\/span><span class=\"s-w\">: os.environ[<\/span><span class=\"s-s\">'UNIPILE_ACCOUNT_ID'<\/span><span class=\"s-w\">],<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">        <\/span><span class=\"s-s\">'to'<\/span><span class=\"s-w\">: json.<\/span><span class=\"s-fn\">dumps<\/span><span class=\"s-w\">([{<\/span><span class=\"s-s\">'display_name'<\/span><span class=\"s-w\">: <\/span><span class=\"s-s\">'Alice'<\/span><span class=\"s-w\">, <\/span><span class=\"s-s\">'identifier'<\/span><span class=\"s-w\">: <\/span><span class=\"s-s\">'alice@acme.com'<\/span><span class=\"s-w\">}]),<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">        <\/span><span class=\"s-s\">'subject'<\/span><span class=\"s-w\">: <\/span><span class=\"s-s\">'Quick update'<\/span><span class=\"s-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">        <\/span><span class=\"s-s\">'body'<\/span><span class=\"s-w\">:    <\/span><span class=\"s-s\">'Hi Alice, just checking in.'<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">    }<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">)<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"snd-block-note\"><strong>Note:<\/strong> The <code style=\"font-family:'Courier New',monospace;font-size:12px;\">body<\/code> field accepts both plain text and HTML. Use <code style=\"font-family:'Courier New',monospace;font-size:12px;\"><pee><\/code> tags for HTML formatting.<\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"snd-block\"><!-- [et_pb_line_break_holder] -->        <div class=\"snd-block-header\"><!-- [et_pb_line_break_holder] -->          <div class=\"snd-block-num\">2<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"snd-block-title\">HTML email with CC and BCC<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"snd-block-tag\">Common<\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"snd-pre\"><code><span class=\"s-k\">import<\/span><span class=\"s-w\"> requests, os, json<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"s-w\">response = requests.<\/span><span class=\"s-fn\">post<\/span><span class=\"s-w\">(<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">    <\/span><span class=\"s-fn\">f<\/span><span class=\"s-s\">'{os.environ[\"UNIPILE_DSN\"]}\/api\/v1\/emails'<\/span><span class=\"s-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">    headers={<\/span><span class=\"s-s\">'X-API-KEY'<\/span><span class=\"s-w\">: os.environ[<\/span><span class=\"s-s\">'UNIPILE_API_KEY'<\/span><span class=\"s-w\">]},<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">    data={<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">        <\/span><span class=\"s-s\">'account_id'<\/span><span class=\"s-w\">: os.environ[<\/span><span class=\"s-s\">'UNIPILE_ACCOUNT_ID'<\/span><span class=\"s-w\">],<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">        <\/span><span class=\"s-s\">'to'<\/span><span class=\"s-w\">:  json.<\/span><span class=\"s-fn\">dumps<\/span><span class=\"s-w\">([{<\/span><span class=\"s-s\">'identifier'<\/span><span class=\"s-w\">: <\/span><span class=\"s-s\">'alice@acme.com'<\/span><span class=\"s-w\">}]),<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">        <\/span><span class=\"s-s\">'cc'<\/span><span class=\"s-w\">:  json.<\/span><span class=\"s-fn\">dumps<\/span><span class=\"s-w\">([{<\/span><span class=\"s-s\">'identifier'<\/span><span class=\"s-w\">: <\/span><span class=\"s-s\">'manager@acme.com'<\/span><span class=\"s-w\">}]),<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">        <\/span><span class=\"s-s\">'bcc'<\/span><span class=\"s-w\">: json.<\/span><span class=\"s-fn\">dumps<\/span><span class=\"s-w\">([{<\/span><span class=\"s-s\">'identifier'<\/span><span class=\"s-w\">: <\/span><span class=\"s-s\">'crm@yourapp.com'<\/span><span class=\"s-w\">}]),<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">        <\/span><span class=\"s-s\">'subject'<\/span><span class=\"s-w\">: <\/span><span class=\"s-s\">'Your invoice is ready'<\/span><span class=\"s-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">        <\/span><span class=\"s-s\">'body'<\/span><span class=\"s-w\">: <\/span><span class=\"s-s\">'<h2>Invoice #1042<\/h2><pee>Please find your invoice attached.<\/pee>'<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">    }<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">)<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"s-c\"># 202 Accepted = queued for delivery<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-fn\">print<\/span><span class=\"s-w\">(response.status_code, response.<\/span><span class=\"s-fn\">json<\/span><span class=\"s-w\">())<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"snd-block\"><!-- [et_pb_line_break_holder] -->        <div class=\"snd-block-header\"><!-- [et_pb_line_break_holder] -->          <div class=\"snd-block-num\">3<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"snd-block-title\">Response handling<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"snd-block-tag\">Production<\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"snd-pre\"><code><span class=\"s-k\">import<\/span><span class=\"s-w\"> requests, os, json<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"s-k\">def<\/span><span class=\"s-w\"> <\/span><span class=\"s-fn\">send_email<\/span><span class=\"s-w\">(to_email: <\/span><span class=\"s-fn\">str<\/span><span class=\"s-w\">, subject: <\/span><span class=\"s-fn\">str<\/span><span class=\"s-w\">, body: <\/span><span class=\"s-fn\">str<\/span><span class=\"s-w\">) -> <\/span><span class=\"s-fn\">dict<\/span><span class=\"s-w\">:<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">    <\/span><span class=\"s-s\">\"\"\"Send email via Unipile email API Python wrapper.\"\"\"<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">    response = requests.<\/span><span class=\"s-fn\">post<\/span><span class=\"s-w\">(<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">        <\/span><span class=\"s-fn\">f<\/span><span class=\"s-s\">'{os.environ[\"UNIPILE_DSN\"]}\/api\/v1\/emails'<\/span><span class=\"s-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">        headers={<\/span><span class=\"s-s\">'X-API-KEY'<\/span><span class=\"s-w\">: os.environ[<\/span><span class=\"s-s\">'UNIPILE_API_KEY'<\/span><span class=\"s-w\">]},<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">        data={<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">            <\/span><span class=\"s-s\">'account_id'<\/span><span class=\"s-w\">: os.environ[<\/span><span class=\"s-s\">'UNIPILE_ACCOUNT_ID'<\/span><span class=\"s-w\">],<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">            <\/span><span class=\"s-s\">'to'<\/span><span class=\"s-w\">:      json.<\/span><span class=\"s-fn\">dumps<\/span><span class=\"s-w\">([{<\/span><span class=\"s-s\">'identifier'<\/span><span class=\"s-w\">: to_email}]),<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">            <\/span><span class=\"s-s\">'subject'<\/span><span class=\"s-w\">: subject,<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">            <\/span><span class=\"s-s\">'body'<\/span><span class=\"s-w\">:    body,<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">        },<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">        timeout=30<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">    )<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-w\">    response.<\/span><span class=\"s-fn\">raise_for_status<\/span><span class=\"s-w\">()  <\/span><span class=\"s-c\"># raises HTTPError on 4xx\/5xx<\/span><!-- [et_pb_line_break_holder] --><span class=\"s-k\">    return<\/span><span class=\"s-w\"> response.<\/span><span class=\"s-fn\">json<\/span><span class=\"s-w\">()  <\/span><span class=\"s-c\"># {'tracking_id': 'msg_...'}<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"snd-block-note\"><strong>Tip:<\/strong> Always pass <code style=\"font-family:'Courier New',monospace;font-size:12px;\">timeout=30<\/code> to avoid hanging forever on network issues. Use <code style=\"font-family:'Courier New',monospace;font-size:12px;\">raise_for_status()<\/code> to bubble HTTP errors as Python exceptions.<\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] --><\/div>[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.27.3&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;0px|0px|0px|0px|false|false&#8221; da_disable_devices=&#8221;off|off|off&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221; da_is_popup=&#8221;off&#8221; da_exit_intent=&#8221;off&#8221; da_has_close=&#8221;on&#8221; da_alt_close=&#8221;off&#8221; da_dark_close=&#8221;off&#8221; da_not_modal=&#8221;on&#8221; da_is_singular=&#8221;off&#8221; da_with_loader=&#8221;off&#8221; da_has_shadow=&#8221;on&#8221;][et_pb_row _builder_version=&#8221;4.27.3&#8243; max_width=&#8221;100%&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_code _builder_version=&#8221;4.27.4&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;]<style><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->#upl-midcta-pyapi, #upl-midcta-pyapi *, #upl-midcta-pyapi *::before, #upl-midcta-pyapi *::after {<!-- [et_pb_line_break_holder] -->  margin:0!important;padding:0!important;box-sizing:border-box!important;border:none!important;<!-- [et_pb_line_break_holder] -->  outline:none!important;font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif!important;<!-- [et_pb_line_break_holder] -->  line-height:normal!important;letter-spacing:normal!important;text-transform:none!important;<!-- [et_pb_line_break_holder] -->  text-decoration:none!important;list-style:none!important;background:transparent!important;border-radius:20px;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-midcta-pyapi { padding:56px 20px!important;background:#0f2736!important; }<!-- [et_pb_line_break_holder] -->#upl-midcta-pyapi .mca-inner { max-width:900px!important;margin:0 auto!important;display:flex!important;align-items:center!important;justify-content:space-between!important;gap:32px!important;flex-wrap:wrap!important; }<!-- [et_pb_line_break_holder] -->#upl-midcta-pyapi .mca-eyebrow {<!-- [et_pb_line_break_holder] -->  display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:rgba(221,223,76,0.18)!important;color:#DDDF4C!important;<!-- [et_pb_line_break_holder] -->  padding:5px 12px!important;border-radius:20px!important;<!-- [et_pb_line_break_holder] -->  font-size:11px!important;font-weight:700!important;<!-- [et_pb_line_break_holder] -->  text-transform:uppercase!important;letter-spacing:0.5px!important;<!-- [et_pb_line_break_holder] -->  margin-bottom:14px!important;width:fit-content!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-midcta-pyapi .mca-title { font-family:'Poppins',sans-serif!important;font-size:26px!important;font-weight:700!important;color:#ffffff!important;line-height:1.3!important;margin-bottom:10px!important; }<!-- [et_pb_line_break_holder] -->#upl-midcta-pyapi .mca-desc { font-size:15px!important;color:rgba(255,255,255,0.75)!important;line-height:1.7!important;max-width:520px!important; }<!-- [et_pb_line_break_holder] -->#upl-midcta-pyapi .mca-actions { display:flex!important;align-items:center!important;gap:14px!important;flex-wrap:wrap!important;margin-top:4px!important; }<!-- [et_pb_line_break_holder] -->#upl-midcta-pyapi .mca-cta-primary {<!-- [et_pb_line_break_holder] -->  display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:#DDDF4C!important;color:#0f2736!important;<!-- [et_pb_line_break_holder] -->  padding:13px 26px!important;border-radius:8px!important;<!-- [et_pb_line_break_holder] -->  font-size:0.9rem!important;font-weight:600!important;<!-- [et_pb_line_break_holder] -->  border:2px solid #DDDF4C!important;<!-- [et_pb_line_break_holder] -->  transition:all 0.3s ease!important;cursor:pointer!important;<!-- [et_pb_line_break_holder] -->  white-space:nowrap!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-midcta-pyapi .mca-cta-primary:hover { transform:translateY(-5px)!important; }<!-- [et_pb_line_break_holder] -->#upl-midcta-pyapi .mca-cta-primary svg { width:15px!important;height:15px!important;stroke:currentColor!important;fill:none!important;stroke-width:2.5!important;stroke-linecap:round!important;stroke-linejoin:round!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->#upl-midcta-pyapi .mca-cta-secondary {<!-- [et_pb_line_break_holder] -->  display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:transparent!important;color:#ffffff!important;<!-- [et_pb_line_break_holder] -->  padding:11px 22px!important;border-radius:8px!important;<!-- [et_pb_line_break_holder] -->  border:2px solid rgba(255,255,255,0.3)!important;<!-- [et_pb_line_break_holder] -->  font-size:0.9rem!important;font-weight:600!important;<!-- [et_pb_line_break_holder] -->  transition:all 0.3s ease!important;cursor:pointer!important;<!-- [et_pb_line_break_holder] -->  white-space:nowrap!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-midcta-pyapi .mca-cta-secondary:hover { border-color:#ffffff!important;color:#ffffff!important; }<!-- [et_pb_line_break_holder] -->#upl-midcta-pyapi .mca-cta-secondary svg { width:15px!important;height:15px!important;stroke:currentColor!important;fill:none!important;stroke-width:2.5!important;stroke-linecap:round!important;stroke-linejoin:round!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->@media(max-width:900px){<!-- [et_pb_line_break_holder] -->  #upl-midcta-pyapi {padding:48px 20px!important;}<!-- [et_pb_line_break_holder] -->  #upl-midcta-pyapi .mca-inner {flex-direction:column!important;align-items:flex-start!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->@media(max-width:600px){<!-- [et_pb_line_break_holder] -->  #upl-midcta-pyapi {padding:40px 16px!important;}<!-- [et_pb_line_break_holder] -->  #upl-midcta-pyapi .mca-title {font-size:22px!important;}<!-- [et_pb_line_break_holder] -->  #upl-midcta-pyapi .mca-actions {flex-direction:column!important;width:100%!important;}<!-- [et_pb_line_break_holder] -->  #upl-midcta-pyapi .mca-cta-primary, #upl-midcta-pyapi .mca-cta-secondary {width:100%!important;justify-content:center!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><\/style><!-- [et_pb_line_break_holder] --><div id=\"upl-midcta-pyapi\"><!-- [et_pb_line_break_holder] -->  <div class=\"mca-inner\"><!-- [et_pb_line_break_holder] -->    <div class=\"mca-left\"><!-- [et_pb_line_break_holder] -->      <div class=\"mca-eyebrow\"><span>Free to start<\/span><\/div><!-- [et_pb_line_break_holder] -->      <div class=\"mca-title\">Try it now &#8211; free API key in 30 seconds<\/div><!-- [et_pb_line_break_holder] -->      <pee class=\"mca-desc\">Get your API key, link a Gmail or Outlook account in minutes, and run the Python examples from this guide against real mailboxes.<\/pee><!-- [et_pb_line_break_holder] -->      <div class=\"mca-actions\"><!-- [et_pb_line_break_holder] -->        <a href=\"https:\/\/dashboard.unipile.com\/signup\/\" target=\"_blank\" class=\"mca-cta-primary\" data-upl-link=\"https:\/\/dashboard.unipile.com\/signup\/\"><svg viewBox=\"0 0 24 24\"><path d=\"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4\"\/><polyline points=\"10 17 15 12 10 7\"\/><line x1=\"15\" y1=\"12\" x2=\"3\" y2=\"12\"\/><\/svg><span>Get your free API key<\/span><\/a><!-- [et_pb_line_break_holder] -->        <a href=\"\/email-api-guide\/\" target=\"_self\" class=\"mca-cta-secondary\" data-upl-link=\"\/email-api-guide\/\"><svg viewBox=\"0 0 24 24\"><path d=\"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z\"\/><path d=\"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z\"\/><\/svg><span>Read the full Email API guide<\/span><\/a><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] --><\/div><!-- [et_pb_line_break_holder] --><script><!-- [et_pb_line_break_holder] -->document.querySelectorAll('#upl-midcta-pyapi [data-upl-link]').forEach(function(el){<!-- [et_pb_line_break_holder] -->  el.addEventListener('click',function(e){<!-- [et_pb_line_break_holder] -->    e.preventDefault();<!-- [et_pb_line_break_holder] -->    var url=el.getAttribute('data-upl-link');<!-- [et_pb_line_break_holder] -->    if(url.includes('unipile.com')||url.startsWith('\/')){window.location.href=url;}else if(url.startsWith('http')){window.open(url,'_blank');}else{window.location.href=url;}<!-- [et_pb_line_break_holder] -->  });<!-- [et_pb_line_break_holder] -->});<!-- [et_pb_line_break_holder] --><\/script>[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.27.3&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;0px|0px|0px|0px|false|false&#8221; da_disable_devices=&#8221;off|off|off&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221; da_is_popup=&#8221;off&#8221; da_exit_intent=&#8221;off&#8221; da_has_close=&#8221;on&#8221; da_alt_close=&#8221;off&#8221; da_dark_close=&#8221;off&#8221; da_not_modal=&#8221;on&#8221; da_is_singular=&#8221;off&#8221; da_with_loader=&#8221;off&#8221; da_has_shadow=&#8221;on&#8221;][et_pb_row _builder_version=&#8221;4.27.3&#8243; max_width=&#8221;100%&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_code _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;]<style><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->#upl-attach-pyapi, #upl-attach-pyapi *, #upl-attach-pyapi *::before, #upl-attach-pyapi *::after {<!-- [et_pb_line_break_holder] -->  margin:0!important;padding:0!important;box-sizing:border-box!important;border:none!important;<!-- [et_pb_line_break_holder] -->  outline:none!important;font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif!important;<!-- [et_pb_line_break_holder] -->  line-height:normal!important;letter-spacing:normal!important;text-transform:none!important;<!-- [et_pb_line_break_holder] -->  text-decoration:none!important;list-style:none!important;background:transparent!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi { padding:72px 20px!important; }<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-inner { max-width:1100px!important;margin:0 auto!important; }<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-eyebrow {<!-- [et_pb_line_break_holder] -->  display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:rgba(59,185,139,0.12)!important;color:#2aaa7e!important;<!-- [et_pb_line_break_holder] -->  padding:6px 14px!important;border-radius:20px!important;<!-- [et_pb_line_break_holder] -->  font-size:12px!important;font-weight:700!important;<!-- [et_pb_line_break_holder] -->  text-transform:uppercase!important;letter-spacing:0.5px!important;<!-- [et_pb_line_break_holder] -->  margin-bottom:16px!important;width:fit-content!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-dot { width:7px!important;height:7px!important;background:#3BB98B!important;border-radius:50%!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-h2 { font-family:'Poppins',sans-serif!important;font-size:35px!important;font-weight:700!important;color:#0f2736!important;line-height:1.2!important;margin-bottom:14px!important;max-width:820px!important; }<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-sub { font-size:17px!important;line-height:1.75!important;color:#383838!important;margin-bottom:40px!important;max-width:100%!important; }<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-grid { display:grid!important;grid-template-columns:1fr 1fr!important;gap:32px!important;align-items:start!important; }<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-editor { border-radius:14px!important;overflow:hidden!important;background:#0d1117!important; }<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-editor-bar { background:#161b22!important;padding:12px 18px!important;display:flex!important;align-items:center!important;gap:8px!important;border-bottom:1px solid rgba(255,255,255,0.06)!important; }<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .a-dot-r {width:12px!important;height:12px!important;border-radius:50%!important;background:#ff5f57!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .a-dot-y {width:12px!important;height:12px!important;border-radius:50%!important;background:#febc2e!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .a-dot-g {width:12px!important;height:12px!important;border-radius:50%!important;background:#28c840!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-fname { color:#8b949e!important;font-size:13px!important;margin-left:6px!important;font-family:'Courier New',monospace!important; }<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-pre { padding:22px 24px!important;font-size:13px!important;line-height:1.8!important;overflow-x:auto!important;background:#0d1117!important; }<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-pre code { font-family:'Courier New',monospace!important;white-space:pre!important;display:block!important; }<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .a-c {color:#8b949e!important;}#upl-attach-pyapi .a-k {color:#ff7b72!important;}#upl-attach-pyapi .a-fn {color:#d2a8ff!important;}#upl-attach-pyapi .a-s {color:#a5d6ff!important;}#upl-attach-pyapi .a-w {color:#e6edf3!important;}#upl-attach-pyapi .a-n {color:#79c0ff!important;}<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-cards { display:flex!important;flex-direction:column!important;gap:16px!important; }<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-card { background:#ffffff!important;border:1px solid #e5e7eb!important;border-radius:12px!important;padding:20px!important; }<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-card-title { font-family:'Poppins',sans-serif!important;font-size:15px!important;font-weight:700!important;color:#0f2736!important;margin-bottom:8px!important; }<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-card-body { font-size:14px!important;color:#718096!important;line-height:1.6!important; }<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-card-body code { font-family:'Courier New',monospace!important;background:#f4f5f7!important;padding:1px 5px!important;border-radius:3px!important;font-size:12px!important;color:#0f2736!important; }<!-- [et_pb_line_break_holder] -->#upl-attach-pyapi .att-limit-strip { margin-top:28px!important;background:#fff8e6!important;border:1px solid rgba(221,183,76,0.3)!important;border-radius:10px!important;padding:16px 20px!important;font-size:14px!important;color:#0f2736!important;line-height:1.6!important; }<!-- [et_pb_line_break_holder] -->@media(max-width:900px){<!-- [et_pb_line_break_holder] -->  #upl-attach-pyapi {padding:50px 20px!important;}<!-- [et_pb_line_break_holder] -->  #upl-attach-pyapi .att-grid {grid-template-columns:1fr!important;}<!-- [et_pb_line_break_holder] -->  #upl-attach-pyapi .att-h2 {font-size:28px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->@media(max-width:600px){<!-- [et_pb_line_break_holder] -->  #upl-attach-pyapi {padding:40px 16px!important;}<!-- [et_pb_line_break_holder] -->  #upl-attach-pyapi .att-h2 {font-size:26px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><\/style><!-- [et_pb_line_break_holder] --><div id=\"upl-attach-pyapi\"><!-- [et_pb_line_break_holder] -->  <span id=\"anchor-attachments\"><\/span><!-- [et_pb_line_break_holder] -->  <div class=\"att-inner\"><!-- [et_pb_line_break_holder] -->    <div class=\"att-eyebrow\"><span class=\"att-dot\"><\/span><span>Attachments<\/span><\/div><!-- [et_pb_line_break_holder] -->    <h2 class=\"att-h2\">Sending Attachments in Python<\/h2><!-- [et_pb_line_break_holder] -->    <pee class=\"att-sub\">Attachments are sent as part of the multipart form data using Python&#8217;s <code style=\"font-family:'Courier New',monospace;background:rgba(0,0,0,0.06);padding:1px 5px;border-radius:3px;font-size:15px;\">files=<\/code> parameter. Open the file in binary mode (<code style=\"font-family:'Courier New',monospace;background:rgba(0,0,0,0.06);padding:1px 5px;border-radius:3px;font-size:15px;\">'rb'<\/code>) &#8211; bytes, not strings.<\/pee><!-- [et_pb_line_break_holder] -->    <div class=\"att-grid\"><!-- [et_pb_line_break_holder] -->      <div class=\"att-editor\"><!-- [et_pb_line_break_holder] -->        <div class=\"att-editor-bar\"><!-- [et_pb_line_break_holder] -->          <span class=\"a-dot-r\"><\/span><span class=\"a-dot-y\"><\/span><span class=\"a-dot-g\"><\/span><!-- [et_pb_line_break_holder] -->          <span class=\"att-fname\">attach.py<\/span><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"att-pre\"><code><span class=\"a-k\">import<\/span><span class=\"a-w\"> requests, os, json<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"a-c\"># Single file attachment<\/span><!-- [et_pb_line_break_holder] --><span class=\"a-k\">with<\/span><span class=\"a-w\"> <\/span><span class=\"a-fn\">open<\/span><span class=\"a-w\">(<\/span><span class=\"a-s\">'invoice.pdf'<\/span><span class=\"a-w\">, <\/span><span class=\"a-s\">'rb'<\/span><span class=\"a-w\">) <\/span><span class=\"a-k\">as<\/span><span class=\"a-w\"> f:<\/span><!-- [et_pb_line_break_holder] --><span class=\"a-w\">    resp = requests.<\/span><span class=\"a-fn\">post<\/span><span class=\"a-w\">(<\/span><!-- [et_pb_line_break_holder] --><span class=\"a-w\">        <\/span><span class=\"a-fn\">f<\/span><span class=\"a-s\">'{os.environ[\"UNIPILE_DSN\"]}\/api\/v1\/emails'<\/span><span class=\"a-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"a-w\">        headers={<\/span><span class=\"a-s\">'X-API-KEY'<\/span><span class=\"a-w\">: os.environ[<\/span><span class=\"a-s\">'UNIPILE_API_KEY'<\/span><span class=\"a-w\">]},<\/span><!-- [et_pb_line_break_holder] --><span class=\"a-w\">        data={<\/span><!-- [et_pb_line_break_holder] --><span class=\"a-w\">            <\/span><span class=\"a-s\">'account_id'<\/span><span class=\"a-w\">: os.environ[<\/span><span class=\"a-s\">'UNIPILE_ACCOUNT_ID'<\/span><span class=\"a-w\">],<\/span><!-- [et_pb_line_break_holder] --><span class=\"a-w\">            <\/span><span class=\"a-s\">'to'<\/span><span class=\"a-w\">: json.<\/span><span class=\"a-fn\">dumps<\/span><span class=\"a-w\">([{<\/span><span class=\"a-s\">'identifier'<\/span><span class=\"a-w\">: <\/span><span class=\"a-s\">'client@example.com'<\/span><span class=\"a-w\">}]),<\/span><!-- [et_pb_line_break_holder] --><span class=\"a-w\">            <\/span><span class=\"a-s\">'subject'<\/span><span class=\"a-w\">: <\/span><span class=\"a-s\">'Invoice attached'<\/span><span class=\"a-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"a-w\">            <\/span><span class=\"a-s\">'body'<\/span><span class=\"a-w\">:    <\/span><span class=\"a-s\">'<pee>Please see the attached invoice.<\/pee>'<\/span><!-- [et_pb_line_break_holder] --><span class=\"a-w\">        },<\/span><!-- [et_pb_line_break_holder] --><span class=\"a-w\">        files={<\/span><span class=\"a-s\">'attachments'<\/span><span class=\"a-w\">: (<\/span><span class=\"a-s\">'invoice.pdf'<\/span><span class=\"a-w\">, f, <\/span><span class=\"a-s\">'application\/pdf'<\/span><span class=\"a-w\">)}<\/span><!-- [et_pb_line_break_holder] --><span class=\"a-w\">    )<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"a-c\"># Multiple attachments: pass a list of tuples<\/span><!-- [et_pb_line_break_holder] --><span class=\"a-c\"># files=[('attachments', ('a.pdf', f1, 'application\/pdf')),<\/span><!-- [et_pb_line_break_holder] --><span class=\"a-c\">#        ('attachments', ('b.png', f2, 'image\/png'))]<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"att-cards\"><!-- [et_pb_line_break_holder] -->        <div class=\"att-card\"><!-- [et_pb_line_break_holder] -->          <div class=\"att-card-title\">Always open in binary mode<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"att-card-body\">Use <code>open('file.pdf', 'rb')<\/code>, not <code>'r'<\/code>. Passing a text file object to <code>files=<\/code> raises a <code>TypeError<\/code>. This is a common Python-specific gotcha when migrating from smtplib.<\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"att-card\"><!-- [et_pb_line_break_holder] -->          <div class=\"att-card-title\">Multiple attachments<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"att-card-body\">Pass a list of tuples to <code>files=<\/code>: each tuple is <code>('attachments', (filename, fileobj, content_type))<\/code>. Requests handles the multipart boundary automatically.<\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"att-card\"><!-- [et_pb_line_break_holder] -->          <div class=\"att-card-title\">In-memory files (BytesIO)<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"att-card-body\">For dynamically generated PDFs or CSV exports, pass a <code>BytesIO<\/code> object directly: <code>from io import BytesIO; buf = BytesIO(pdf_bytes)<\/code> then <code>('report.pdf', buf, 'application\/pdf')<\/code>.<\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"att-limit-strip\"><!-- [et_pb_line_break_holder] -->          <strong>Provider limits:<\/strong> Gmail allows up to 25 MB total per send. Outlook allows up to 20 MB. IMAP limits depend on your server configuration. For files above these limits, send a download link instead.<!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] --><\/div>[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.27.4&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;0px||0px||false|false&#8221; da_disable_devices=&#8221;off|off|off&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221; da_is_popup=&#8221;off&#8221; da_exit_intent=&#8221;off&#8221; da_has_close=&#8221;on&#8221; da_alt_close=&#8221;off&#8221; da_dark_close=&#8221;off&#8221; da_not_modal=&#8221;on&#8221; da_is_singular=&#8221;off&#8221; da_with_loader=&#8221;off&#8221; da_has_shadow=&#8221;on&#8221;][et_pb_row _builder_version=&#8221;4.27.4&#8243; background_color=&#8221;RGBA(255,255,255,0)&#8221; max_width=&#8221;100%&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.27.4&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_code _builder_version=&#8221;4.27.4&#8243; background_color=&#8221;RGBA(255,255,255,0)&#8221; hover_enabled=&#8221;0&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221; sticky_enabled=&#8221;0&#8243;]<style><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->#upl-cta-py-3, #upl-cta-py-3 *, #upl-cta-py-3 *::before, #upl-cta-py-3 *::after {<!-- [et_pb_line_break_holder] -->  margin:0!important;padding:0!important;box-sizing:border-box!important;border:none!important;<!-- [et_pb_line_break_holder] -->  outline:none!important;font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif!important;<!-- [et_pb_line_break_holder] -->  line-height:normal!important;letter-spacing:normal!important;text-transform:none!important;<!-- [et_pb_line_break_holder] -->  text-decoration:none!important;list-style:none!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-cta-py-3 { padding:32px 20px!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-3 .cy3-inner { max-width:1100px!important;margin:0 auto!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-3 .cy3-card { background:#ffffff!important;border-radius:16px!important;padding:24px 28px!important;display:flex!important;align-items:center!important;justify-content:space-between!important;gap:24px!important;flex-wrap:wrap!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-3 .cy3-left { display:flex!important;align-items:center!important;gap:16px!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-3 .cy3-icon { width:44px!important;height:44px!important;min-width:44px!important;border-radius:12px!important;background:rgba(221,223,76,0.18)!important;display:flex!important;align-items:center!important;justify-content:center!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-3 .cy3-icon svg { width:20px!important;height:20px!important;stroke:#8a8c2e!important;fill:none!important;stroke-width:2!important;stroke-linecap:round!important;stroke-linejoin:round!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-3 .cy3-text-title { font-family:'Poppins',sans-serif!important;font-size:16px!important;font-weight:700!important;color:#0f2736!important;line-height:1.3!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-3 .cy3-text-desc { font-size:14px!important;color:#64748b!important;line-height:1.5!important;margin-top:3px!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-3 .cy3-actions { display:flex!important;align-items:center!important;gap:12px!important;flex-wrap:wrap!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-3 .cy3-cta-primary { display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:#DDDF4C!important;color:#0f2736!important;<!-- [et_pb_line_break_holder] -->  padding:12px 22px!important;border-radius:8px!important;<!-- [et_pb_line_break_holder] -->  font-size:0.88rem!important;font-weight:600!important;<!-- [et_pb_line_break_holder] -->  border:2px solid #DDDF4C!important;<!-- [et_pb_line_break_holder] -->  transition:all 0.3s ease!important;cursor:pointer!important;<!-- [et_pb_line_break_holder] -->  white-space:nowrap!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-cta-py-3 .cy3-cta-primary:hover { transform:translateY(-2px)!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-3 .cy3-cta-secondary { display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:transparent!important;color:#0f2736!important;<!-- [et_pb_line_break_holder] -->  padding:10px 20px!important;border-radius:8px!important;<!-- [et_pb_line_break_holder] -->  border:2px solid #0f2736!important;<!-- [et_pb_line_break_holder] -->  font-size:0.88rem!important;font-weight:600!important;<!-- [et_pb_line_break_holder] -->  transition:all 0.3s ease!important;cursor:pointer!important;<!-- [et_pb_line_break_holder] -->  white-space:nowrap!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-cta-py-3 .cy3-cta-secondary:hover { background:#0f2736!important;color:#ffffff!important; }<!-- [et_pb_line_break_holder] -->#upl-cta-py-3 .cy3-cta-primary svg, #upl-cta-py-3 .cy3-cta-secondary svg { width:14px!important;height:14px!important;stroke:currentColor!important;fill:none!important;stroke-width:2.5!important;stroke-linecap:round!important;stroke-linejoin:round!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->@media(max-width:700px){<!-- [et_pb_line_break_holder] -->  #upl-cta-py-3 .cy3-card {flex-direction:column!important;align-items:flex-start!important;}<!-- [et_pb_line_break_holder] -->  #upl-cta-py-3 .cy3-cta-primary, #upl-cta-py-3 .cy3-cta-secondary {width:100%!important;justify-content:center!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><\/style><!-- [et_pb_line_break_holder] --><div id=\"upl-cta-py-3\"><!-- [et_pb_line_break_holder] -->  <div class=\"cy3-inner\"><!-- [et_pb_line_break_holder] -->    <div class=\"cy3-card\"><!-- [et_pb_line_break_holder] -->      <div class=\"cy3-left\"><!-- [et_pb_line_break_holder] -->        <div class=\"cy3-icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div><!-- [et_pb_line_break_holder] -->          <div class=\"cy3-text-title\"><span>Need larger attachments or higher send limits?<\/span><\/div><!-- [et_pb_line_break_holder] -->          <div class=\"cy3-text-desc\"><span>Unipile plans scale from prototypes to production workloads. Compare quotas on the pricing page.<\/span><\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"cy3-actions\"><!-- [et_pb_line_break_holder] -->        <a href=\"https:\/\/www.unipile.com\/pricing\/\" class=\"cy3-cta-primary\" data-upl-link=\"https:\/\/www.unipile.com\/pricing\/\"><svg viewBox=\"0 0 24 24\"><path d=\"M5 12h14\"\/><path d=\"M12 5l7 7-7 7\"\/><\/svg><span>View pricing plans<\/span><\/a><!-- [et_pb_line_break_holder] -->        <a href=\"https:\/\/dashboard.unipile.com\/signup\/\" target=\"_blank\" class=\"cy3-cta-secondary\" data-upl-link=\"https:\/\/dashboard.unipile.com\/signup\/\"><svg viewBox=\"0 0 24 24\"><path d=\"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4\"\/><polyline points=\"10 17 15 12 10 7\"\/><line x1=\"15\" y1=\"12\" x2=\"3\" y2=\"12\"\/><\/svg><span>Start for free<\/span><\/a><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] --><\/div><!-- [et_pb_line_break_holder] --><script><!-- [et_pb_line_break_holder] -->document.querySelectorAll('#upl-cta-py-3 [data-upl-link]').forEach(function(el){<!-- [et_pb_line_break_holder] -->  el.addEventListener('click',function(e){<!-- [et_pb_line_break_holder] -->    e.preventDefault();<!-- [et_pb_line_break_holder] -->    var url=el.getAttribute('data-upl-link');<!-- [et_pb_line_break_holder] -->    if(url.includes('unipile.com')||url.startsWith('\/')){window.location.href=url;}else if(url.startsWith('http')){window.open(url,'_blank');}else{window.location.href=url;}<!-- [et_pb_line_break_holder] -->  });<!-- [et_pb_line_break_holder] -->});<!-- [et_pb_line_break_holder] --><\/script>[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.27.3&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;0px|0px|0px|0px|false|false&#8221; da_disable_devices=&#8221;off|off|off&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221; da_is_popup=&#8221;off&#8221; da_exit_intent=&#8221;off&#8221; da_has_close=&#8221;on&#8221; da_alt_close=&#8221;off&#8221; da_dark_close=&#8221;off&#8221; da_not_modal=&#8221;on&#8221; da_is_singular=&#8221;off&#8221; da_with_loader=&#8221;off&#8221; da_has_shadow=&#8221;on&#8221;][et_pb_row _builder_version=&#8221;4.27.3&#8243; max_width=&#8221;100%&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_code _builder_version=&#8221;4.27.4&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;]<!DOCTYPE html><!-- [et_pb_line_break_holder] --><html lang=\"en\"><!-- [et_pb_line_break_holder] --><head><!-- [et_pb_line_break_holder] --><meta charset=\"UTF-8\"><!-- [et_pb_line_break_holder] --><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><!-- [et_pb_line_break_holder] --><title>Unipile &#8211; Advanced Python API<\/title><!-- [et_pb_line_break_holder] --><link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;family=Poppins:wght@700&#038;display=swap\" rel=\"stylesheet\"><!-- [et_pb_line_break_holder] --><\/head><!-- [et_pb_line_break_holder] --><body style=\"margin:0;padding:0;background:#f4f5f7;\"><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><style><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->#upl-adv-pyapi, #upl-adv-pyapi *, #upl-adv-pyapi *::before, #upl-adv-pyapi *::after {<!-- [et_pb_line_break_holder] -->  margin:0!important;padding:0!important;box-sizing:border-box!important;border:none!important;<!-- [et_pb_line_break_holder] -->  outline:none!important;font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif!important;<!-- [et_pb_line_break_holder] -->  line-height:normal!important;letter-spacing:normal!important;text-transform:none!important;<!-- [et_pb_line_break_holder] -->  text-decoration:none!important;list-style:none!important;background:transparent!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi { padding:72px 20px!important;background:#f4f5f7!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-inner { max-width:1100px!important;margin:0 auto!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-eyebrow {<!-- [et_pb_line_break_holder] -->  display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:rgba(221,223,76,0.18)!important;color:#8a8c2e!important;<!-- [et_pb_line_break_holder] -->  padding:6px 14px!important;border-radius:20px!important;<!-- [et_pb_line_break_holder] -->  font-size:12px!important;font-weight:700!important;<!-- [et_pb_line_break_holder] -->  text-transform:uppercase!important;letter-spacing:0.5px!important;<!-- [et_pb_line_break_holder] -->  margin-bottom:16px!important;width:fit-content!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-dot { width:7px!important;height:7px!important;background:#DDDF4C!important;border-radius:50%!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-h2 { font-family:'Poppins',sans-serif!important;font-size:35px!important;font-weight:700!important;color:#0f2736!important;line-height:1.2!important;margin-bottom:14px!important;max-width:820px!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-sub { font-size:17px!important;line-height:1.75!important;color:#383838!important;margin-bottom:40px!important;max-width:100%!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-sub a { color:#2aaa7e!important;font-weight:600!important;text-decoration:underline!important; }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->\/* NOUVEAU : Conteneur blanc qui englobe les 3 d\u00e9roulants *\/<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-blocks-wrapper {<!-- [et_pb_line_break_holder] -->  background:#ffffff!important;<!-- [et_pb_line_break_holder] -->  border-radius:20px!important;<!-- [et_pb_line_break_holder] -->  padding:24px!important;<!-- [et_pb_line_break_holder] -->  border:1px solid #e5e7eb!important;<!-- [et_pb_line_break_holder] -->  box-shadow:0 2px 8px rgba(15,39,54,0.04)!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-blocks { display:flex!important;flex-direction:column!important;gap:16px!important; }<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->details.adv-acc { background:#f8f9fa!important;border:1px solid #e5e7eb!important;border-radius:14px!important;overflow:hidden!important;transition:all 0.2s ease!important; }<!-- [et_pb_line_break_holder] -->details.adv-acc:hover { border-color:#d1d5db!important; }<!-- [et_pb_line_break_holder] -->details.adv-acc[open] { border-color:#3BB98B!important;background:#ffffff!important;box-shadow:0 4px 12px rgba(59,185,139,0.10)!important; }<!-- [et_pb_line_break_holder] -->details.adv-acc summary { list-style:none!important;cursor:pointer!important;padding:20px 24px!important;display:flex!important;align-items:center!important;gap:14px!important;user-select:none!important; }<!-- [et_pb_line_break_holder] -->details.adv-acc summary::-webkit-details-marker { display:none!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-num { width:38px!important;height:38px!important;min-width:38px!important;border-radius:10px!important;background:rgba(221,223,76,0.18)!important;color:#8a8c2e!important;display:flex!important;align-items:center!important;justify-content:center!important;font-family:'Poppins',sans-serif!important;font-size:14px!important;font-weight:700!important; }<!-- [et_pb_line_break_holder] -->details.adv-acc[open] .adv-num { background:rgba(59,185,139,0.15)!important;color:#2aaa7e!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-sum-title { font-family:'Poppins',sans-serif!important;font-size:16px!important;font-weight:700!important;color:#0f2736!important;flex:1!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-chevron { color:#6b7280!important;transition:transform 0.25s ease,color 0.2s ease!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->details.adv-acc[open] .adv-chevron { transform:rotate(180deg)!important;color:#3BB98B!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-body { padding:0 24px 24px 76px!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-body p { font-size:15px!important;color:#383838!important;line-height:1.75!important;margin-bottom:16px!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-body p:last-child { margin-bottom:0!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-body a { color:#2aaa7e!important;font-weight:600!important;text-decoration:underline!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-editor { border-radius:12px!important;overflow:hidden!important;background:#0d1117!important;margin-top:16px!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-editor-bar { background:#161b22!important;padding:10px 18px!important;display:flex!important;align-items:center!important;gap:8px!important;border-bottom:1px solid rgba(255,255,255,0.06)!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-dot-r {width:11px!important;height:11px!important;border-radius:50%!important;background:#ff5f57!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-dot-y {width:11px!important;height:11px!important;border-radius:50%!important;background:#febc2e!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-dot-g {width:11px!important;height:11px!important;border-radius:50%!important;background:#28c840!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-fname { color:#8b949e!important;font-size:12px!important;margin-left:6px!important;font-family:'Courier New',monospace!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-pre { padding:18px 22px!important;font-size:12.5px!important;line-height:1.8!important;overflow-x:auto!important;background:#0d1117!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .adv-pre code { font-family:'Courier New',monospace!important;white-space:pre!important;display:block!important; }<!-- [et_pb_line_break_holder] -->#upl-adv-pyapi .v-c {color:#8b949e!important;}#upl-adv-pyapi .v-k {color:#ff7b72!important;}#upl-adv-pyapi .v-fn {color:#d2a8ff!important;}#upl-adv-pyapi .v-s {color:#a5d6ff!important;}#upl-adv-pyapi .v-w {color:#e6edf3!important;}#upl-adv-pyapi .v-n {color:#79c0ff!important;}<!-- [et_pb_line_break_holder] -->@media(max-width:900px){<!-- [et_pb_line_break_holder] -->  #upl-adv-pyapi {padding:50px 20px!important;}<!-- [et_pb_line_break_holder] -->  #upl-adv-pyapi .adv-h2 {font-size:28px!important;}<!-- [et_pb_line_break_holder] -->  #upl-adv-pyapi .adv-blocks-wrapper {padding:16px!important;}<!-- [et_pb_line_break_holder] -->  #upl-adv-pyapi .adv-body {padding:0 16px 20px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->@media(max-width:600px){<!-- [et_pb_line_break_holder] -->  #upl-adv-pyapi {padding:40px 16px!important;}<!-- [et_pb_line_break_holder] -->  #upl-adv-pyapi .adv-h2 {font-size:26px!important;}<!-- [et_pb_line_break_holder] -->  #upl-adv-pyapi .adv-blocks-wrapper {padding:12px!important;border-radius:16px!important;}<!-- [et_pb_line_break_holder] -->  details.adv-acc summary {padding:16px 18px!important;}<!-- [et_pb_line_break_holder] -->  #upl-adv-pyapi .adv-body {padding:0 14px 18px 14px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><\/style><!-- [et_pb_line_break_holder] --><div id=\"upl-adv-pyapi\"><!-- [et_pb_line_break_holder] -->  <span id=\"anchor-advanced\"><\/span><!-- [et_pb_line_break_holder] -->  <div class=\"adv-inner\"><!-- [et_pb_line_break_holder] -->    <div class=\"adv-eyebrow\"><span class=\"adv-dot\"><\/span><span>Advanced<\/span><\/div><!-- [et_pb_line_break_holder] -->    <h2 class=\"adv-h2\">Replies, Threads &#038; Tracking<\/h2><!-- [et_pb_line_break_holder] -->    <pee class=\"adv-sub\">For <a href=\"\/send-email-on-behalf-of-user-api\/\">sending email on behalf of a user<\/a>, threading, and webhook-based delivery tracking, here are the Python patterns you need.<\/pee><!-- [et_pb_line_break_holder] -->    <div class=\"adv-blocks-wrapper\"><!-- [et_pb_line_break_holder] -->      <div class=\"adv-blocks\"><!-- [et_pb_line_break_holder] -->        <details class=\"adv-acc\"><!-- [et_pb_line_break_holder] -->          <summary><div class=\"adv-num\">01<\/div><span class=\"adv-sum-title\">Threading with in_reply_to<\/span><svg class=\"adv-chevron\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><polyline points=\"6 9 12 15 18 9\"\/><\/svg><\/summary><!-- [et_pb_line_break_holder] -->          <div class=\"adv-body\"><!-- [et_pb_line_break_holder] -->            <pee>To reply within an existing thread, pass the <code style=\"font-family:'Courier New',monospace;background:rgba(0,0,0,0.06);padding:1px 5px;border-radius:3px;font-size:13px;\">in_reply_to<\/code> field with the <code style=\"font-family:'Courier New',monospace;background:rgba(0,0,0,0.06);padding:1px 5px;border-radius:3px;font-size:13px;\">tracking_id<\/code> of the email you want to reply to. Unipile handles the <code style=\"font-family:'Courier New',monospace;background:rgba(0,0,0,0.06);padding:1px 5px;border-radius:3px;font-size:13px;\">References<\/code> and <code style=\"font-family:'Courier New',monospace;background:rgba(0,0,0,0.06);padding:1px 5px;border-radius:3px;font-size:13px;\">In-Reply-To<\/code> headers automatically.<\/pee><!-- [et_pb_line_break_holder] -->            <div class=\"adv-editor\"><!-- [et_pb_line_break_holder] -->              <div class=\"adv-editor-bar\"><span class=\"adv-dot-r\"><\/span><span class=\"adv-dot-y\"><\/span><span class=\"adv-dot-g\"><\/span><span class=\"adv-fname\">reply.py<\/span><\/div><!-- [et_pb_line_break_holder] -->              <div class=\"adv-pre\"><code><span class=\"v-w\">requests.<\/span><span class=\"v-fn\">post<\/span><span class=\"v-w\">(<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">    <\/span><span class=\"v-fn\">f<\/span><span class=\"v-s\">'{DSN}\/api\/v1\/emails'<\/span><span class=\"v-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">    headers={<\/span><span class=\"v-s\">'X-API-KEY'<\/span><span class=\"v-w\">: <\/span><span class=\"v-n\">API_KEY<\/span><span class=\"v-w\">},<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">    data={<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">        <\/span><span class=\"v-s\">'account_id'<\/span><span class=\"v-w\">:  <\/span><span class=\"v-n\">ACCOUNT_ID<\/span><span class=\"v-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">        <\/span><span class=\"v-s\">'to'<\/span><span class=\"v-w\">:          json.<\/span><span class=\"v-fn\">dumps<\/span><span class=\"v-w\">([{<\/span><span class=\"v-s\">'identifier'<\/span><span class=\"v-w\">: <\/span><span class=\"v-s\">'alice@acme.com'<\/span><span class=\"v-w\">}]),<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">        <\/span><span class=\"v-s\">'subject'<\/span><span class=\"v-w\">:     <\/span><span class=\"v-s\">'Re: Your question'<\/span><span class=\"v-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">        <\/span><span class=\"v-s\">'body'<\/span><span class=\"v-w\">:        <\/span><span class=\"v-s\">'<pee>Following up on your message.<\/pee>'<\/span><span class=\"v-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">        <\/span><span class=\"v-s\">'in_reply_to'<\/span><span class=\"v-w\">: <\/span><span class=\"v-s\">'msg_original_tracking_id'<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">    }<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">)<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->            <\/div><!-- [et_pb_line_break_holder] -->          <\/div><!-- [et_pb_line_break_holder] -->        <\/details><!-- [et_pb_line_break_holder] -->        <details class=\"adv-acc\"><!-- [et_pb_line_break_holder] -->          <summary><div class=\"adv-num\">02<\/div><span class=\"adv-sum-title\">Webhooks in Python (Flask example)<\/span><svg class=\"adv-chevron\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><polyline points=\"6 9 12 15 18 9\"\/><\/svg><\/summary><!-- [et_pb_line_break_holder] -->          <div class=\"adv-body\"><!-- [et_pb_line_break_holder] -->            <pee>Register a webhook URL in your Unipile dashboard to receive delivery events (sent, bounced, opened). Here is a minimal Flask receiver:<\/pee><!-- [et_pb_line_break_holder] -->            <div class=\"adv-editor\"><!-- [et_pb_line_break_holder] -->              <div class=\"adv-editor-bar\"><span class=\"adv-dot-r\"><\/span><span class=\"adv-dot-y\"><\/span><span class=\"adv-dot-g\"><\/span><span class=\"adv-fname\">webhook_flask.py<\/span><\/div><!-- [et_pb_line_break_holder] -->              <div class=\"adv-pre\"><code><span class=\"v-k\">from<\/span><span class=\"v-w\"> flask <\/span><span class=\"v-k\">import<\/span><span class=\"v-w\"> Flask, request, jsonify<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-k\">import<\/span><span class=\"v-w\"> logging<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"v-w\">app = <\/span><span class=\"v-fn\">Flask<\/span><span class=\"v-w\">(<\/span><span class=\"v-n\">__name__<\/span><span class=\"v-w\">)<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">logging.<\/span><span class=\"v-fn\">basicConfig<\/span><span class=\"v-w\">(level=logging.<\/span><span class=\"v-n\">INFO<\/span><span class=\"v-w\">)<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"v-w\">@app.<\/span><span class=\"v-fn\">route<\/span><span class=\"v-w\">(<\/span><span class=\"v-s\">'\/webhook\/email'<\/span><span class=\"v-w\">, methods=[<\/span><span class=\"v-s\">'POST'<\/span><span class=\"v-w\">])<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-k\">def<\/span><span class=\"v-w\"> <\/span><span class=\"v-fn\">email_webhook<\/span><span class=\"v-w\">():<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">    event = request.<\/span><span class=\"v-fn\">get_json<\/span><span class=\"v-w\">()<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">    event_type = event.<\/span><span class=\"v-fn\">get<\/span><span class=\"v-w\">(<\/span><span class=\"v-s\">'type'<\/span><span class=\"v-w\">)<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">    tracking_id = event.<\/span><span class=\"v-fn\">get<\/span><span class=\"v-w\">(<\/span><span class=\"v-s\">'tracking_id'<\/span><span class=\"v-w\">)<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">    logging.<\/span><span class=\"v-fn\">info<\/span><span class=\"v-w\">(<\/span><span class=\"v-fn\">f<\/span><span class=\"v-s\">'Email event: {event_type} for {tracking_id}'<\/span><span class=\"v-w\">)<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-k\">    return<\/span><span class=\"v-w\"> <\/span><span class=\"v-fn\">jsonify<\/span><span class=\"v-w\">(ok=<\/span><span class=\"v-n\">True<\/span><span class=\"v-w\">), <\/span><span class=\"v-n\">200<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->            <\/div><!-- [et_pb_line_break_holder] -->          <\/div><!-- [et_pb_line_break_holder] -->        <\/details><!-- [et_pb_line_break_holder] -->        <details class=\"adv-acc\"><!-- [et_pb_line_break_holder] -->          <summary><div class=\"adv-num\">03<\/div><span class=\"adv-sum-title\">Idempotency keys<\/span><svg class=\"adv-chevron\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><polyline points=\"6 9 12 15 18 9\"\/><\/svg><\/summary><!-- [et_pb_line_break_holder] -->          <div class=\"adv-body\"><!-- [et_pb_line_break_holder] -->            <pee>To prevent duplicate sends on network retry, pass a unique <code style=\"font-family:'Courier New',monospace;background:rgba(0,0,0,0.06);padding:1px 5px;border-radius:3px;font-size:13px;\">Idempotency-Key<\/code> header. If the same key is sent twice, Unipile returns the original response without sending a second email.<\/pee><!-- [et_pb_line_break_holder] -->            <div class=\"adv-editor\"><!-- [et_pb_line_break_holder] -->              <div class=\"adv-editor-bar\"><span class=\"adv-dot-r\"><\/span><span class=\"adv-dot-y\"><\/span><span class=\"adv-dot-g\"><\/span><span class=\"adv-fname\">idempotency.py<\/span><\/div><!-- [et_pb_line_break_holder] -->              <div class=\"adv-pre\"><code><span class=\"v-k\">import<\/span><span class=\"v-w\"> uuid, requests, os, json<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"v-w\">key = <\/span><span class=\"v-fn\">str<\/span><span class=\"v-w\">(uuid.<\/span><span class=\"v-fn\">uuid4<\/span><span class=\"v-w\">())  <\/span><span class=\"v-c\"># generate once, store in DB<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"v-w\">requests.<\/span><span class=\"v-fn\">post<\/span><span class=\"v-w\">(<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">    <\/span><span class=\"v-fn\">f<\/span><span class=\"v-s\">'{os.environ[\"UNIPILE_DSN\"]}\/api\/v1\/emails'<\/span><span class=\"v-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">    headers={<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">        <\/span><span class=\"v-s\">'X-API-KEY'<\/span><span class=\"v-w\">:       os.environ[<\/span><span class=\"v-s\">'UNIPILE_API_KEY'<\/span><span class=\"v-w\">],<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">        <\/span><span class=\"v-s\">'Idempotency-Key'<\/span><span class=\"v-w\">: key<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">    },<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">    data={<\/span><span class=\"v-s\">'account_id'<\/span><span class=\"v-w\">: os.environ[<\/span><span class=\"v-s\">'UNIPILE_ACCOUNT_ID'<\/span><span class=\"v-w\">],<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">          <\/span><span class=\"v-s\">'to'<\/span><span class=\"v-w\">: json.<\/span><span class=\"v-fn\">dumps<\/span><span class=\"v-w\">([{<\/span><span class=\"v-s\">'identifier'<\/span><span class=\"v-w\">: <\/span><span class=\"v-s\">'alice@acme.com'<\/span><span class=\"v-w\">}]),<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">          <\/span><span class=\"v-s\">'subject'<\/span><span class=\"v-w\">: <\/span><span class=\"v-s\">'Welcome!'<\/span><span class=\"v-w\">, <\/span><span class=\"v-s\">'body'<\/span><span class=\"v-w\">: <\/span><span class=\"v-s\">'Hi!'<\/span><span class=\"v-w\">}<\/span><!-- [et_pb_line_break_holder] --><span class=\"v-w\">)<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->            <\/div><!-- [et_pb_line_break_holder] -->          <\/div><!-- [et_pb_line_break_holder] -->        <\/details><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] --><\/div><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><\/body><!-- [et_pb_line_break_holder] --><\/html>[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.27.3&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;0px|0px|0px|0px|false|false&#8221; da_disable_devices=&#8221;off|off|off&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221; da_is_popup=&#8221;off&#8221; da_exit_intent=&#8221;off&#8221; da_has_close=&#8221;on&#8221; da_alt_close=&#8221;off&#8221; da_dark_close=&#8221;off&#8221; da_not_modal=&#8221;on&#8221; da_is_singular=&#8221;off&#8221; da_with_loader=&#8221;off&#8221; da_has_shadow=&#8221;on&#8221;][et_pb_row _builder_version=&#8221;4.27.3&#8243; max_width=&#8221;100%&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_code _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;]<style><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->#upl-err-pyapi, #upl-err-pyapi *, #upl-err-pyapi *::before, #upl-err-pyapi *::after {<!-- [et_pb_line_break_holder] -->  margin:0!important;padding:0!important;box-sizing:border-box!important;border:none!important;<!-- [et_pb_line_break_holder] -->  outline:none!important;font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif!important;<!-- [et_pb_line_break_holder] -->  line-height:normal!important;letter-spacing:normal!important;text-transform:none!important;<!-- [et_pb_line_break_holder] -->  text-decoration:none!important;list-style:none!important;background:transparent!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-err-pyapi { padding:72px 20px!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-inner { max-width:1100px!important;margin:0 auto!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-eyebrow {<!-- [et_pb_line_break_holder] -->  display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:rgba(59,185,139,0.12)!important;color:#2aaa7e!important;<!-- [et_pb_line_break_holder] -->  padding:6px 14px!important;border-radius:20px!important;<!-- [et_pb_line_break_holder] -->  font-size:12px!important;font-weight:700!important;<!-- [et_pb_line_break_holder] -->  text-transform:uppercase!important;letter-spacing:0.5px!important;<!-- [et_pb_line_break_holder] -->  margin-bottom:16px!important;width:fit-content!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-dot { width:7px!important;height:7px!important;background:#3BB98B!important;border-radius:50%!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-h2 { font-family:'Poppins',sans-serif!important;font-size:35px!important;font-weight:700!important;color:#0f2736!important;line-height:1.2!important;margin-bottom:14px!important;max-width:820px!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-sub { font-size:17px!important;line-height:1.75!important;color:#383838!important;margin-bottom:40px!important;max-width:100%!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-grid { display:grid!important;grid-template-columns:1fr 1fr!important;gap:32px!important;align-items:start!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-table { background:#ffffff!important;border:1px solid #e5e7eb!important;border-radius:16px!important;overflow:hidden!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-table table { width:100%!important;border-collapse:collapse!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-table thead tr { background:#f4f5f7!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-table th { padding:12px 16px!important;font-size:12px!important;font-weight:700!important;color:#64748b!important;text-transform:uppercase!important;letter-spacing:0.5px!important;text-align:left!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-table td { padding:12px 16px!important;font-size:14px!important;color:#383838!important;border-top:1px solid #f0f1f3!important;vertical-align:top!important;line-height:1.5!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-table td:first-child { font-family:'Courier New',monospace!important;font-weight:700!important;color:#ff7b72!important;font-size:13px!important;white-space:nowrap!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-table td:last-child { color:#718096!important;font-size:13px!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-editor { border-radius:14px!important;overflow:hidden!important;background:#0d1117!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-editor-bar { background:#161b22!important;padding:12px 18px!important;display:flex!important;align-items:center!important;gap:8px!important;border-bottom:1px solid rgba(255,255,255,0.06)!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .e-dot-r {width:12px!important;height:12px!important;border-radius:50%!important;background:#ff5f57!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .e-dot-y {width:12px!important;height:12px!important;border-radius:50%!important;background:#febc2e!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .e-dot-g {width:12px!important;height:12px!important;border-radius:50%!important;background:#28c840!important;display:inline-block!important;flex-shrink:0!important;}<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-fname { color:#8b949e!important;font-size:13px!important;margin-left:6px!important;font-family:'Courier New',monospace!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-pre { padding:20px 24px!important;font-size:13px!important;line-height:1.8!important;overflow-x:auto!important;background:#0d1117!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .err-pre code { font-family:'Courier New',monospace!important;white-space:pre!important;display:block!important; }<!-- [et_pb_line_break_holder] -->#upl-err-pyapi .r-c {color:#8b949e!important;}#upl-err-pyapi .r-k {color:#ff7b72!important;}#upl-err-pyapi .r-fn {color:#d2a8ff!important;}#upl-err-pyapi .r-s {color:#a5d6ff!important;}#upl-err-pyapi .r-w {color:#e6edf3!important;}#upl-err-pyapi .r-n {color:#79c0ff!important;}<!-- [et_pb_line_break_holder] -->@media(max-width:900px){<!-- [et_pb_line_break_holder] -->  #upl-err-pyapi {padding:50px 20px!important;}<!-- [et_pb_line_break_holder] -->  #upl-err-pyapi .err-grid {grid-template-columns:1fr!important;}<!-- [et_pb_line_break_holder] -->  #upl-err-pyapi .err-h2 {font-size:28px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->@media(max-width:600px){<!-- [et_pb_line_break_holder] -->  #upl-err-pyapi {padding:40px 16px!important;}<!-- [et_pb_line_break_holder] -->  #upl-err-pyapi .err-h2 {font-size:26px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><\/style><!-- [et_pb_line_break_holder] --><div id=\"upl-err-pyapi\"><!-- [et_pb_line_break_holder] -->  <span id=\"anchor-errors\"><\/span><!-- [et_pb_line_break_holder] -->  <div class=\"err-inner\"><!-- [et_pb_line_break_holder] -->    <div class=\"err-eyebrow\"><span class=\"err-dot\"><\/span><span>Production<\/span><\/div><!-- [et_pb_line_break_holder] -->    <h2 class=\"err-h2\">Error Handling &#038; Retries<\/h2><!-- [et_pb_line_break_holder] -->    <pee class=\"err-sub\">Production Python code for the email API needs proper exception handling, structured logging, and automatic retries with exponential backoff using the <code style=\"font-family:'Courier New',monospace;background:rgba(0,0,0,0.06);padding:1px 5px;border-radius:3px;font-size:15px;\">tenacity<\/code> library.<\/pee><!-- [et_pb_line_break_holder] -->    <div class=\"err-grid\"><!-- [et_pb_line_break_holder] -->      <div class=\"err-table\"><!-- [et_pb_line_break_holder] -->        <table><!-- [et_pb_line_break_holder] -->          <thead><tr><th>HTTP Code<\/th><th>Meaning<\/th><th>Action<\/th><\/tr><\/thead><!-- [et_pb_line_break_holder] -->          <tbody><!-- [et_pb_line_break_holder] -->            <tr><td>202<\/td><td>Accepted &#8211; queued for delivery<\/td><td>Store tracking_id<\/td><\/tr><!-- [et_pb_line_break_holder] -->            <tr><td>400<\/td><td>Bad request (invalid fields)<\/td><td>Fix payload, do not retry<\/td><\/tr><!-- [et_pb_line_break_holder] -->            <tr><td>401<\/td><td>Invalid API key<\/td><td>Check UNIPILE_API_KEY<\/td><\/tr><!-- [et_pb_line_break_holder] -->            <tr><td>403<\/td><td>Account not authorized<\/td><td>Re-link account<\/td><\/tr><!-- [et_pb_line_break_holder] -->            <tr><td>404<\/td><td>Account ID not found<\/td><td>Check UNIPILE_ACCOUNT_ID<\/td><\/tr><!-- [et_pb_line_break_holder] -->            <tr><td>429<\/td><td>Rate limited<\/td><td>Backoff + retry (see code)<\/td><\/tr><!-- [et_pb_line_break_holder] -->            <tr><td>500<\/td><td>Server error<\/td><td>Retry after 5s delay<\/td><\/tr><!-- [et_pb_line_break_holder] -->          <\/tbody><!-- [et_pb_line_break_holder] -->        <\/table><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"err-editor\"><!-- [et_pb_line_break_holder] -->        <div class=\"err-editor-bar\"><!-- [et_pb_line_break_holder] -->          <span class=\"e-dot-r\"><\/span><span class=\"e-dot-y\"><\/span><span class=\"e-dot-g\"><\/span><!-- [et_pb_line_break_holder] -->          <span class=\"err-fname\">retry.py<\/span><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->        <div class=\"err-pre\"><code><span class=\"r-k\">import<\/span><span class=\"r-w\"> requests, os, json, logging<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-k\">from<\/span><span class=\"r-w\"> tenacity <\/span><span class=\"r-k\">import<\/span><span class=\"r-w\"> (<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">    retry, stop_after_attempt,<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">    wait_exponential, retry_if_exception_type<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">)<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"r-w\">logging.<\/span><span class=\"r-fn\">basicConfig<\/span><span class=\"r-w\">(level=logging.<\/span><span class=\"r-n\">INFO<\/span><span class=\"r-w\">)<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">logger = logging.<\/span><span class=\"r-fn\">getLogger<\/span><span class=\"r-w\">(<\/span><span class=\"r-n\">__name__<\/span><span class=\"r-w\">)<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"r-k\">class<\/span><span class=\"r-w\"> <\/span><span class=\"r-fn\">RateLimitError<\/span><span class=\"r-w\">(Exception):<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">    <\/span><span class=\"r-k\">pass<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"r-w\">@<\/span><span class=\"r-fn\">retry<\/span><span class=\"r-w\">(<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">    stop=<\/span><span class=\"r-fn\">stop_after_attempt<\/span><span class=\"r-w\">(4),<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">    wait=<\/span><span class=\"r-fn\">wait_exponential<\/span><span class=\"r-w\">(multiplier=1, min=2, max=30),<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">    retry=<\/span><span class=\"r-fn\">retry_if_exception_type<\/span><span class=\"r-w\">(<\/span><span class=\"r-fn\">RateLimitError<\/span><span class=\"r-w\">)<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">)<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-k\">def<\/span><span class=\"r-w\"> <\/span><span class=\"r-fn\">send_with_retry<\/span><span class=\"r-w\">(to: <\/span><span class=\"r-fn\">str<\/span><span class=\"r-w\">, subject: <\/span><span class=\"r-fn\">str<\/span><span class=\"r-w\">, body: <\/span><span class=\"r-fn\">str<\/span><span class=\"r-w\">) -> <\/span><span class=\"r-fn\">dict<\/span><span class=\"r-w\">:<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">    resp = requests.<\/span><span class=\"r-fn\">post<\/span><span class=\"r-w\">(<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">        <\/span><span class=\"r-fn\">f<\/span><span class=\"r-s\">'{os.environ[\"UNIPILE_DSN\"]}\/api\/v1\/emails'<\/span><span class=\"r-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">        headers={<\/span><span class=\"r-s\">'X-API-KEY'<\/span><span class=\"r-w\">: os.environ[<\/span><span class=\"r-s\">'UNIPILE_API_KEY'<\/span><span class=\"r-w\">]},<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">        data={<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">            <\/span><span class=\"r-s\">'account_id'<\/span><span class=\"r-w\">: os.environ[<\/span><span class=\"r-s\">'UNIPILE_ACCOUNT_ID'<\/span><span class=\"r-w\">],<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">            <\/span><span class=\"r-s\">'to'<\/span><span class=\"r-w\">:      json.<\/span><span class=\"r-fn\">dumps<\/span><span class=\"r-w\">([{<\/span><span class=\"r-s\">'identifier'<\/span><span class=\"r-w\">: to}]),<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">            <\/span><span class=\"r-s\">'subject'<\/span><span class=\"r-w\">: subject, <\/span><span class=\"r-s\">'body'<\/span><span class=\"r-w\">: body<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">        },<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">        timeout=30<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">    )<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-k\">    if<\/span><span class=\"r-w\"> resp.status_code == <\/span><span class=\"r-n\">429<\/span><span class=\"r-w\">:<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">        logger.<\/span><span class=\"r-fn\">warning<\/span><span class=\"r-w\">(<\/span><span class=\"r-s\">'Rate limited, backing off...'<\/span><span class=\"r-w\">)<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">        <\/span><span class=\"r-k\">raise<\/span><span class=\"r-w\"> <\/span><span class=\"r-fn\">RateLimitError<\/span><span class=\"r-w\">()<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-w\">    resp.<\/span><span class=\"r-fn\">raise_for_status<\/span><span class=\"r-w\">()<\/span><!-- [et_pb_line_break_holder] --><span class=\"r-k\">    return<\/span><span class=\"r-w\"> resp.<\/span><span class=\"r-fn\">json<\/span><span class=\"r-w\">()<\/span><\/code><\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] --><\/div>[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.27.3&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;0px|0px|0px|0px|false|false&#8221; da_disable_devices=&#8221;off|off|off&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221; da_is_popup=&#8221;off&#8221; da_exit_intent=&#8221;off&#8221; da_has_close=&#8221;on&#8221; da_alt_close=&#8221;off&#8221; da_dark_close=&#8221;off&#8221; da_not_modal=&#8221;on&#8221; da_is_singular=&#8221;off&#8221; da_with_loader=&#8221;off&#8221; da_has_shadow=&#8221;on&#8221;][et_pb_row _builder_version=&#8221;4.27.3&#8243; max_width=&#8221;100%&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_code _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;]<style><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->#upl-sec-pyapi, #upl-sec-pyapi *, #upl-sec-pyapi *::before, #upl-sec-pyapi *::after {<!-- [et_pb_line_break_holder] -->  margin:0!important;padding:0!important;box-sizing:border-box!important;border:none!important;<!-- [et_pb_line_break_holder] -->  outline:none!important;font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif!important;<!-- [et_pb_line_break_holder] -->  line-height:normal!important;letter-spacing:normal!important;text-transform:none!important;<!-- [et_pb_line_break_holder] -->  text-decoration:none!important;list-style:none!important;background:transparent!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi { padding:72px 20px!important;background:#f4f5f7!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-inner { max-width:1100px!important;margin:0 auto!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-eyebrow {<!-- [et_pb_line_break_holder] -->  display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:rgba(221,223,76,0.18)!important;color:#8a8c2e!important;<!-- [et_pb_line_break_holder] -->  padding:6px 14px!important;border-radius:20px!important;<!-- [et_pb_line_break_holder] -->  font-size:12px!important;font-weight:700!important;<!-- [et_pb_line_break_holder] -->  text-transform:uppercase!important;letter-spacing:0.5px!important;<!-- [et_pb_line_break_holder] -->  margin-bottom:16px!important;width:fit-content!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-dot { width:7px!important;height:7px!important;background:#DDDF4C!important;border-radius:50%!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-h2 { font-family:'Poppins',sans-serif!important;font-size:35px!important;font-weight:700!important;color:#0f2736!important;line-height:1.2!important;margin-bottom:14px!important;max-width:820px!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-sub { font-size:17px!important;line-height:1.75!important;color:#383838!important;margin-bottom:40px!important;max-width:100%!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-sub a { color:#2aaa7e!important;font-weight:600!important;text-decoration:underline!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-grid { display:grid!important;grid-template-columns:repeat(3,1fr)!important;gap:20px!important;margin-bottom:32px!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-card { background:#ffffff!important;border:1px solid #e5e7eb!important;border-radius:16px!important;padding:24px!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-card-icon { width:40px!important;height:40px!important;border-radius:10px!important;background:rgba(59,185,139,0.12)!important;display:flex!important;align-items:center!important;justify-content:center!important;margin-bottom:14px!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-card-icon svg { width:20px!important;height:20px!important;stroke:#3BB98B!important;fill:none!important;stroke-width:2!important;stroke-linecap:round!important;stroke-linejoin:round!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-card-title { font-family:'Poppins',sans-serif!important;font-size:15px!important;font-weight:700!important;color:#0f2736!important;margin-bottom:8px!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-card-body { font-size:14px!important;color:#718096!important;line-height:1.6!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-card-body code { font-family:'Courier New',monospace!important;background:#f4f5f7!important;padding:1px 5px!important;border-radius:3px!important;font-size:12px!important;color:#0f2736!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-alert { background:#fff3cd!important;border:1px solid rgba(221,183,76,0.35)!important;border-radius:12px!important;padding:18px 22px!important;display:flex!important;gap:14px!important;align-items:flex-start!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-alert svg { width:20px!important;height:20px!important;stroke:#8a6d00!important;fill:none!important;stroke-width:2!important;flex-shrink:0!important;margin-top:2px!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-alert-text { font-size:14px!important;color:#5a4200!important;line-height:1.65!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-alert-text strong { color:#3d2e00!important; }<!-- [et_pb_line_break_holder] -->#upl-sec-pyapi .sec-alert-text a { color:#2aaa7e!important;font-weight:600!important;text-decoration:underline!important; }<!-- [et_pb_line_break_holder] -->@media(max-width:900px){<!-- [et_pb_line_break_holder] -->  #upl-sec-pyapi {padding:50px 20px!important;}<!-- [et_pb_line_break_holder] -->  #upl-sec-pyapi .sec-grid {grid-template-columns:1fr 1fr!important;}<!-- [et_pb_line_break_holder] -->  #upl-sec-pyapi .sec-h2 {font-size:28px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->@media(max-width:600px){<!-- [et_pb_line_break_holder] -->  #upl-sec-pyapi {padding:40px 16px!important;}<!-- [et_pb_line_break_holder] -->  #upl-sec-pyapi .sec-grid {grid-template-columns:1fr!important;}<!-- [et_pb_line_break_holder] -->  #upl-sec-pyapi .sec-h2 {font-size:26px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><\/style><!-- [et_pb_line_break_holder] --><div id=\"upl-sec-pyapi\"><!-- [et_pb_line_break_holder] -->  <span id=\"anchor-security\"><\/span><!-- [et_pb_line_break_holder] -->  <div class=\"sec-inner\"><!-- [et_pb_line_break_holder] -->    <div class=\"sec-eyebrow\"><span class=\"sec-dot\"><\/span><span>Security<\/span><\/div><!-- [et_pb_line_break_holder] -->    <h2 class=\"sec-h2\">Security Best Practices in Python<\/h2><!-- [et_pb_line_break_holder] -->    <pee class=\"sec-sub\">For a complete guide to protecting your email API integration, see the <a href=\"\/secure-email-api\/\">email API security guide<\/a>. Here are the Python-specific essentials.<\/pee><!-- [et_pb_line_break_holder] -->    <div class=\"sec-grid\"><!-- [et_pb_line_break_holder] -->      <div class=\"sec-card\"><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-icon\"><svg viewBox=\"0 0 24 24\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"\/><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-title\">Never hardcode keys<\/div><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-body\">Use <code>os.environ<\/code> or <code>python-dotenv<\/code>. Never put <code>UNIPILE_API_KEY<\/code> as a string literal in your source code. If accidentally pushed to Git, rotate the key immediately from your dashboard.<\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"sec-card\"><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"\/><polyline points=\"22 4 12 14.01 9 11.01\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-title\">Virtual environments<\/div><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-body\">Always isolate dependencies with <code>venv<\/code> or <code>conda<\/code>. This prevents dependency confusion attacks and makes your <code>requirements.txt<\/code> auditable. Pin versions in production.<\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"sec-card\"><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-title\">OAuth token refresh<\/div><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-body\">Unipile handles OAuth token refresh automatically for Gmail and Outlook. You never store or rotate provider tokens yourself &#8211; just keep your <code>UNIPILE_API_KEY<\/code> valid.<\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"sec-card\"><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-icon\"><svg viewBox=\"0 0 24 24\"><polyline points=\"16 18 22 12 16 6\"\/><polyline points=\"8 6 2 12 8 18\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-title\">Server-side only<\/div><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-body\">Never call the Unipile API from client-side code (browser or mobile app). In Flask\/Django\/FastAPI, always keep API calls in server-side views or background tasks (Celery).<\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"sec-card\"><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-icon\"><svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"\/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-title\">Validate webhook payloads<\/div><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-body\">When receiving Unipile webhooks in Flask or FastAPI, validate the request origin via secret header or HMAC signature before processing the event. Never trust raw incoming payloads blindly.<\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"sec-card\"><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-icon\"><svg viewBox=\"0 0 24 24\"><path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"\/><polyline points=\"14 2 14 8 20 8\"\/><line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\"\/><line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\"\/><polyline points=\"10 9 9 9 8 9\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-title\">Audit &#038; logging<\/div><!-- [et_pb_line_break_holder] -->        <div class=\"sec-card-body\">Log <code>tracking_id<\/code> for every sent email to enable delivery audits. Use Python&#8217;s standard <code>logging<\/code> module &#8211; never <code>print()<\/code> in production. Ship logs to a SIEM for compliance-heavy use cases.<\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->    <div class=\"sec-alert\"><!-- [et_pb_line_break_holder] -->      <svg viewBox=\"0 0 24 24\"><path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\"\/><line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\"\/><line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"\/><\/svg><!-- [et_pb_line_break_holder] -->      <div class=\"sec-alert-text\"><strong>DKIM &#038; SPF:<\/strong> These are DNS-level configurations, not Python code. Set up SPF and DKIM records for your sending domain. Read the full <a href=\"\/secure-email-api\/\">email API security guide<\/a> for step-by-step DNS setup.<\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] --><\/div>[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.27.3&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;0px|0px|0px|0px|false|false&#8221; da_disable_devices=&#8221;off|off|off&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221; da_is_popup=&#8221;off&#8221; da_exit_intent=&#8221;off&#8221; da_has_close=&#8221;on&#8221; da_alt_close=&#8221;off&#8221; da_dark_close=&#8221;off&#8221; da_not_modal=&#8221;on&#8221; da_is_singular=&#8221;off&#8221; da_with_loader=&#8221;off&#8221; da_has_shadow=&#8221;on&#8221;][et_pb_row _builder_version=&#8221;4.27.3&#8243; max_width=&#8221;100%&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_code _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;]<style><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] -->#upl-pit-pyapi, #upl-pit-pyapi *, #upl-pit-pyapi *::before, #upl-pit-pyapi *::after {<!-- [et_pb_line_break_holder] -->  margin:0!important;padding:0!important;box-sizing:border-box!important;border:none!important;<!-- [et_pb_line_break_holder] -->  outline:none!important;font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif!important;<!-- [et_pb_line_break_holder] -->  line-height:normal!important;letter-spacing:normal!important;text-transform:none!important;<!-- [et_pb_line_break_holder] -->  text-decoration:none!important;list-style:none!important;background:transparent!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi { padding:72px 20px!important; }<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi .pit-inner { max-width:1100px!important;margin:0 auto!important; }<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi .pit-eyebrow {<!-- [et_pb_line_break_holder] -->  display:inline-flex!important;align-items:center!important;gap:8px!important;<!-- [et_pb_line_break_holder] -->  background:rgba(59,185,139,0.12)!important;color:#2aaa7e!important;<!-- [et_pb_line_break_holder] -->  padding:6px 14px!important;border-radius:20px!important;<!-- [et_pb_line_break_holder] -->  font-size:12px!important;font-weight:700!important;<!-- [et_pb_line_break_holder] -->  text-transform:uppercase!important;letter-spacing:0.5px!important;<!-- [et_pb_line_break_holder] -->  margin-bottom:16px!important;width:fit-content!important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi .pit-dot { width:7px!important;height:7px!important;background:#3BB98B!important;border-radius:50%!important;flex-shrink:0!important; }<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi .pit-h2 { font-family:'Poppins',sans-serif!important;font-size:35px!important;font-weight:700!important;color:#0f2736!important;line-height:1.2!important;margin-bottom:14px!important;max-width:820px!important; }<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi .pit-sub { font-size:17px!important;line-height:1.75!important;color:#383838!important;margin-bottom:40px!important;max-width:100%!important; }<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi .pit-sub a { color:#2aaa7e!important;font-weight:600!important;text-decoration:underline!important; }<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi .pit-list { display:flex!important;flex-direction:column!important;gap:16px!important; }<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi .pit-item { display:flex!important;gap:16px!important;background:#ffffff!important;border:1px solid #e5e7eb!important;border-radius:14px!important;padding:22px!important;align-items:flex-start!important; }<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi .pit-icon { width:40px!important;height:40px!important;min-width:40px!important;border-radius:10px!important;background:rgba(255,123,114,0.1)!important;display:flex!important;align-items:center!important;justify-content:center!important; }<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi .pit-icon svg { width:20px!important;height:20px!important;stroke:#ff7b72!important;fill:none!important;stroke-width:2!important;stroke-linecap:round!important;stroke-linejoin:round!important; }<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi .pit-body {}<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi .pit-title { font-family:'Poppins',sans-serif!important;font-size:15px!important;font-weight:700!important;color:#0f2736!important;margin-bottom:6px!important; }<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi .pit-desc { font-size:14px!important;color:#718096!important;line-height:1.65!important; }<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi .pit-desc code { font-family:'Courier New',monospace!important;background:#f4f5f7!important;padding:1px 5px!important;border-radius:3px!important;font-size:12px!important;color:#0f2736!important; }<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi .pit-desc a { color:#2aaa7e!important;font-weight:600!important;text-decoration:underline!important; }<!-- [et_pb_line_break_holder] -->#upl-pit-pyapi .pit-fix { margin-top:8px!important;display:inline-flex!important;align-items:center!important;gap:6px!important;background:rgba(59,185,139,0.1)!important;color:#2aaa7e!important;padding:4px 10px!important;border-radius:20px!important;font-size:12px!important;font-weight:600!important; }<!-- [et_pb_line_break_holder] -->@media(max-width:900px){<!-- [et_pb_line_break_holder] -->  #upl-pit-pyapi {padding:50px 20px!important;}<!-- [et_pb_line_break_holder] -->  #upl-pit-pyapi .pit-h2 {font-size:28px!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->@media(max-width:600px){<!-- [et_pb_line_break_holder] -->  #upl-pit-pyapi {padding:40px 16px!important;}<!-- [et_pb_line_break_holder] -->  #upl-pit-pyapi .pit-h2 {font-size:26px!important;}<!-- [et_pb_line_break_holder] -->  #upl-pit-pyapi .pit-item {flex-direction:column!important;}<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><\/style><!-- [et_pb_line_break_holder] --><div id=\"upl-pit-pyapi\"><!-- [et_pb_line_break_holder] -->  <span id=\"anchor-pitfalls\"><\/span><!-- [et_pb_line_break_holder] -->  <div class=\"pit-inner\"><!-- [et_pb_line_break_holder] -->    <div class=\"pit-eyebrow\"><span class=\"pit-dot\"><\/span><span>Pitfalls<\/span><\/div><!-- [et_pb_line_break_holder] -->    <h2 class=\"pit-h2\">Common Python-Specific Pitfalls<\/h2><!-- [et_pb_line_break_holder] -->    <pee class=\"pit-sub\">These are the most common mistakes Python developers make when integrating the email API. If you are on Node.js instead, see our <a href=\"\/send-email-api-javascript\/\">JavaScript send email API tutorial<\/a>.<\/pee><!-- [et_pb_line_break_holder] -->    <div class=\"pit-list\"><!-- [et_pb_line_break_holder] -->      <div class=\"pit-item\"><!-- [et_pb_line_break_holder] -->        <div class=\"pit-icon\"><svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"\/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"pit-body\"><!-- [et_pb_line_break_holder] -->          <div class=\"pit-title\">Using <code>json=<\/code> instead of <code>data=<\/code><\/div><!-- [et_pb_line_break_holder] -->          <div class=\"pit-desc\">The Unipile send endpoint requires <code>multipart\/form-data<\/code>, not JSON. Always use <code>requests.post(..., data={...})<\/code>. Using <code>json={...}<\/code> will return a 400 error. The <code>to<\/code>, <code>cc<\/code>, and <code>bcc<\/code> fields are JSON strings inside the form data &#8211; use <code>json.dumps()<\/code> to encode the recipient array.<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"pit-fix\"><svg viewBox=\"0 0 24 24\" width=\"12\" height=\"12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><polyline points=\"20 6 9 17 4 12\"\/><\/svg><span>Fix: use data= with json.dumps() for recipient arrays<\/span><\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"pit-item\"><!-- [et_pb_line_break_holder] -->        <div class=\"pit-icon\"><svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"\/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"pit-body\"><!-- [et_pb_line_break_holder] -->          <div class=\"pit-title\">Opening attachment files in text mode<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"pit-desc\">Always open file attachments with <code>open('file.pdf', 'rb')<\/code> &#8211; binary mode. Text mode (<code>'r'<\/code>) raises a <code>TypeError<\/code> when passed to the <code>files=<\/code> parameter. For in-memory content, use <code>io.BytesIO<\/code>.<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"pit-fix\"><svg viewBox=\"0 0 24 24\" width=\"12\" height=\"12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><polyline points=\"20 6 9 17 4 12\"\/><\/svg><span>Fix: always open files as &#8216;rb&#8217;<\/span><\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"pit-item\"><!-- [et_pb_line_break_holder] -->        <div class=\"pit-icon\"><svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"\/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"pit-body\"><!-- [et_pb_line_break_holder] -->          <div class=\"pit-title\">Mixing sync and async (asyncio)<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"pit-desc\">The <code>requests<\/code> library is synchronous. Calling it inside an <code>async def<\/code> function blocks the event loop. Use <code>httpx.AsyncClient<\/code> or <code>aiohttp.ClientSession<\/code> for async Python contexts (FastAPI, async Django views, asyncio scripts).<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"pit-fix\"><svg viewBox=\"0 0 24 24\" width=\"12\" height=\"12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><polyline points=\"20 6 9 17 4 12\"\/><\/svg><span>Fix: use httpx.AsyncClient for async\/await contexts<\/span><\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"pit-item\"><!-- [et_pb_line_break_holder] -->        <div class=\"pit-icon\"><svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"\/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"pit-body\"><!-- [et_pb_line_break_holder] -->          <div class=\"pit-title\">Missing timeout on requests<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"pit-desc\">By default, <code>requests.post()<\/code> waits forever. A hung connection will block your thread (or Celery worker) indefinitely. Always pass <code>timeout=30<\/code> (connect timeout, read timeout in seconds).<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"pit-fix\"><svg viewBox=\"0 0 24 24\" width=\"12\" height=\"12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><polyline points=\"20 6 9 17 4 12\"\/><\/svg><span>Fix: always pass timeout=(5, 30) to requests.post()<\/span><\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"pit-item\"><!-- [et_pb_line_break_holder] -->        <div class=\"pit-icon\"><svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"\/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"pit-body\"><!-- [et_pb_line_break_holder] -->          <div class=\"pit-title\">Timezone-naive datetimes in scheduling<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"pit-desc\">If you schedule emails with a timestamp field, always use timezone-aware datetimes: <code>from datetime import datetime, timezone; datetime.now(timezone.utc)<\/code>. Naive datetimes cause silent off-by-hours errors in multi-region deployments.<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"pit-fix\"><svg viewBox=\"0 0 24 24\" width=\"12\" height=\"12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><polyline points=\"20 6 9 17 4 12\"\/><\/svg><span>Fix: always use timezone.utc for datetime objects<\/span><\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"pit-item\"><!-- [et_pb_line_break_holder] -->        <div class=\"pit-icon\"><svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"\/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->        <div class=\"pit-body\"><!-- [et_pb_line_break_holder] -->          <div class=\"pit-title\">GIL impact on threaded high-volume sends<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"pit-desc\">Python&#8217;s GIL limits true thread parallelism for CPU-bound work, but HTTP requests are I\/O-bound &#8211; threads work fine. For high-volume sends (1000+\/day), use a thread pool (<code>concurrent.futures.ThreadPoolExecutor<\/code>) or offload to a Celery queue.<\/div><!-- [et_pb_line_break_holder] -->          <div class=\"pit-fix\"><svg viewBox=\"0 0 24 24\" width=\"12\" height=\"12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"><polyline points=\"20 6 9 17 4 12\"\/><\/svg><span>Fix: use ThreadPoolExecutor or Celery for batch sends<\/span><\/div><!-- [et_pb_line_break_holder] -->        <\/div><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] --><\/div>[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.27.3&#8243; background_color=&#8221;transparent&#8221; custom_padding=&#8221;0px|0px|0px|0px|false|false&#8221; da_disable_devices=&#8221;off|off|off&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221; da_is_popup=&#8221;off&#8221; da_exit_intent=&#8221;off&#8221; da_has_close=&#8221;on&#8221; da_alt_close=&#8221;off&#8221; da_dark_close=&#8221;off&#8221; da_not_modal=&#8221;on&#8221; da_is_singular=&#8221;off&#8221; da_with_loader=&#8221;off&#8221; da_has_shadow=&#8221;on&#8221;][et_pb_row _builder_version=&#8221;4.27.3&#8243; max_width=&#8221;100%&#8221; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;][et_pb_code _builder_version=&#8221;4.27.3&#8243; global_colors_info=&#8221;{}&#8221; theme_builder_area=&#8221;post_content&#8221;]<div id=\"upl-faq-pyapi\"><!-- [et_pb_line_break_holder] --><style><!-- [et_pb_line_break_holder] -->#upl-faq-pyapi,<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi *,<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi *::before,<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi *::after {<!-- [et_pb_line_break_holder] -->  box-sizing: border-box !important;<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important; padding: 80px 20px !important; max-width: 900px !important; margin: 0 auto !important; background: #f4f5f7 !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-header { text-align: center !important; margin-bottom: 60px !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-title { font-family: 'Poppins', sans-serif !important; font-size: clamp(32px, 5vw, 38px) !important; font-weight: 700 !important; color: #0f2736 !important; margin: 0 0 16px !important; line-height: 1.2 !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-subtitle { font-size: 17px !important; color: #383838 !important; max-width: 700px !important; margin: 0 auto !important; line-height: 1.6 !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-list { display: flex !important; flex-direction: column !important; gap: 12px !important; margin: 0 !important; padding: 0 !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-item { background: #ffffff !important; border: 1px solid #e5e7eb !important; border-radius: 16px !important; overflow: hidden !important; transition: all 0.3s ease !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-item:hover { border-color: #3BB98B !important; box-shadow: 0 4px 20px rgba(59,185,139,0.08) !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-item.active { border-color: #3BB98B !important; box-shadow: 0 8px 30px rgba(59,185,139,0.12) !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-question { width: 100% !important; display: flex !important; align-items: flex-start !important; justify-content: space-between !important; gap: 20px !important; padding: 24px 28px !important; background: transparent !important; border: none !important; cursor: pointer !important; text-align: left !important; transition: all 0.2s ease !important; margin: 0 !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-question-content { display: flex !important; align-items: flex-start !important; gap: 16px !important; flex: 1 !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-number { flex-shrink: 0 !important; padding: 6px 12px !important; background: rgba(59,185,139,0.12) !important; color: #3BB98B !important; border-radius: 20px !important; display: flex !important; align-items: center !important; justify-content: center !important; font-size: 0.8rem !important; font-weight: 600 !important; transition: all 0.3s ease !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-item.active .upl-faq-number { background: rgba(59,185,139,0.2) !important; color: #2a9d6e !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-question-text { font-family: 'Poppins', sans-serif !important; font-size: 1.1rem !important; font-weight: 600 !important; color: #0f2736 !important; line-height: 1.4 !important; padding-top: 4px !important; margin: 0 !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-icon { flex-shrink: 0 !important; width: 36px !important; height: 36px !important; background: #f4f5f7 !important; border-radius: 50% !important; display: flex !important; align-items: center !important; justify-content: center !important; transition: all 0.3s ease !important; margin-top: 2px !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-icon svg { width: 18px !important; height: 18px !important; color: #64748b !important; transition: all 0.3s ease !important; display: block !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-item:hover .upl-faq-icon { background: rgba(59,185,139,0.1) !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-item:hover .upl-faq-icon svg { color: #3BB98B !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-item.active .upl-faq-icon { background: #3BB98B !important; transform: rotate(45deg) !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-item.active .upl-faq-icon svg { color: #ffffff !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-answer { max-height: 0 !important; overflow: hidden !important; transition: max-height 0.4s ease !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-item.active .upl-faq-answer { max-height: 800px !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-answer-content { padding: 0 28px 28px 76px !important; color: #475569 !important; font-size: 1rem !important; line-height: 1.7 !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-answer-content p { margin: 0 0 12px !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-answer-content p:last-child { margin-bottom: 0 !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-answer-content code { font-family: monospace !important; font-size: 0.875rem !important; background: rgba(0,0,0,0.06) !important; padding: 1px 6px !important; border-radius: 3px !important; color: #0f2736 !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-answer-content strong { font-weight: 700 !important; color: #0f2736 !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-answer-content a { color: #2aaa7e !important; font-weight: 600 !important; text-decoration: underline !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-answer-content .faq-mini-code { background: #0d1117 !important; border-radius: 10px !important; padding: 14px 18px !important; margin-top: 12px !important; overflow-x: auto !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-answer-content .faq-mini-code code { font-family: 'Courier New', monospace !important; font-size: 12.5px !important; line-height: 1.8 !important; white-space: pre !important; display: block !important; background: transparent !important; padding: 0 !important; border-radius: 0 !important; color: #e6edf3 !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .fq-c { color: #8b949e !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .fq-k { color: #ff7b72 !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .fq-fn { color: #d2a8ff !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .fq-s { color: #a5d6ff !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .fq-w { color: #e6edf3 !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-cta { margin-top: 50px !important; display: flex !important; align-items: center !important; justify-content: space-between !important; gap: 20px !important; padding: 20px 28px !important; background: #ffffff !important; border: 1px solid #e5e7eb !important; border-radius: 12px !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-cta-text { color: #475569 !important; font-size: 1rem !important; margin: 0 !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-cta-button { display: inline-flex !important; align-items: center !important; gap: 10px !important; background: #DDDF4C !important; color: #0F2836 !important; padding: 13px 20px !important; border-radius: 8px !important; text-decoration: none !important; font-weight: 700 !important; font-size: 1rem !important; border: none !important; cursor: pointer !important; transition: all 0.3s ease !important; white-space: nowrap !important; flex-shrink: 0 !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-cta-button:hover { transform: translateY(-2px) !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-cta-button svg { width: 18px !important; height: 18px !important; display: block !important; transition: transform 0.3s ease !important; }<!-- [et_pb_line_break_holder] -->#upl-faq-pyapi .upl-faq-cta-button:hover svg { transform: translateX(4px) !important; }<!-- [et_pb_line_break_holder] -->@media (max-width: 768px) {<!-- [et_pb_line_break_holder] -->  #upl-faq-pyapi { padding: 60px 16px !important; }<!-- [et_pb_line_break_holder] -->  #upl-faq-pyapi .upl-faq-header { margin-bottom: 40px !important; }<!-- [et_pb_line_break_holder] -->  #upl-faq-pyapi .upl-faq-question { padding: 20px !important; gap: 16px !important; }<!-- [et_pb_line_break_holder] -->  #upl-faq-pyapi .upl-faq-question-content { gap: 12px !important; }<!-- [et_pb_line_break_holder] -->  #upl-faq-pyapi .upl-faq-question-text { font-size: 1rem !important; padding-top: 2px !important; }<!-- [et_pb_line_break_holder] -->  #upl-faq-pyapi .upl-faq-icon { width: 32px !important; height: 32px !important; }<!-- [et_pb_line_break_holder] -->  #upl-faq-pyapi .upl-faq-icon svg { width: 16px !important; height: 16px !important; }<!-- [et_pb_line_break_holder] -->  #upl-faq-pyapi .upl-faq-answer-content { padding: 0 20px 20px 60px !important; font-size: 0.95rem !important; }<!-- [et_pb_line_break_holder] -->  #upl-faq-pyapi .upl-faq-cta { padding: 24px 20px !important; margin-top: 40px !important; flex-direction: column !important; text-align: center !important; gap: 16px !important; }<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] -->@media (max-width: 480px) {<!-- [et_pb_line_break_holder] -->  #upl-faq-pyapi .upl-faq-answer-content { padding: 0 20px 20px 20px !important; }<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><\/style><!-- [et_pb_line_break_holder] --><span id=\"anchor-faq\" style=\"display:block;position:relative;top:-80px;visibility:hidden;\"><\/span><!-- [et_pb_line_break_holder] --><div class=\"upl-faq-header\"><!-- [et_pb_line_break_holder] -->  <h2 class=\"upl-faq-title\">Frequently Asked Questions<\/h2><!-- [et_pb_line_break_holder] -->  <pee class=\"upl-faq-subtitle\">Common questions about using the email API in Python with the Unipile unified email API.<\/pee><!-- [et_pb_line_break_holder] --><\/div><!-- [et_pb_line_break_holder] --><div class=\"upl-faq-list\"><!-- [et_pb_line_break_holder] -->  <div class=\"upl-faq-item\"><!-- [et_pb_line_break_holder] -->    <button class=\"upl-faq-question\" aria-expanded=\"false\"><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-question-content\"><!-- [et_pb_line_break_holder] -->        <span class=\"upl-faq-number\">01<\/span><!-- [et_pb_line_break_holder] -->        <span class=\"upl-faq-question-text\">How do I send email in Python without SMTP?<\/span><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->    <\/button><!-- [et_pb_line_break_holder] -->    <div class=\"upl-faq-answer\"><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-answer-content\"><pee>Use the Unipile unified email API instead of smtplib or a direct SMTP connection. Install <code>requests<\/code>, get your API key and DSN from the Unipile dashboard, link a Gmail or Outlook account via OAuth, then POST to <code>\/api\/v1\/emails<\/code> with your <code>account_id<\/code>, <code>to<\/code>, <code>subject<\/code>, and <code>body<\/code>. No SMTP server, no port 587, no TLS configuration needed in your Python code.<\/pee><\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] -->  <div class=\"upl-faq-item\"><!-- [et_pb_line_break_holder] -->    <button class=\"upl-faq-question\" aria-expanded=\"false\"><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-question-content\"><!-- [et_pb_line_break_holder] -->        <span class=\"upl-faq-number\">02<\/span><!-- [et_pb_line_break_holder] -->        <span class=\"upl-faq-question-text\">Can I use this with Django, Flask, or FastAPI?<\/span><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->    <\/button><!-- [et_pb_line_break_holder] -->    <div class=\"upl-faq-answer\"><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-answer-content\"><pee><strong>Django:<\/strong> call the API in a view or management command. For async Django (3.1+), use <code>httpx.AsyncClient<\/code> in async views.<\/pee><pee><strong>Flask:<\/strong> call the API in a route handler server-side. Never call it from a Jinja template or client-side JS. Use Flask-Celery to offload high-volume sends to background workers.<\/pee><pee><strong>FastAPI:<\/strong> use <code>httpx.AsyncClient<\/code> inside <code>async def<\/code> endpoints. The synchronous <code>requests<\/code> library blocks the async event loop &#8211; always use an async HTTP client in FastAPI.<\/pee><\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] -->  <div class=\"upl-faq-item\"><!-- [et_pb_line_break_holder] -->    <button class=\"upl-faq-question\" aria-expanded=\"false\"><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-question-content\"><!-- [et_pb_line_break_holder] -->        <span class=\"upl-faq-number\">03<\/span><!-- [et_pb_line_break_holder] -->        <span class=\"upl-faq-question-text\">What is the difference between smtplib and a unified email API?<\/span><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->    <\/button><!-- [et_pb_line_break_holder] -->    <div class=\"upl-faq-answer\"><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-answer-content\"><pee><code>smtplib<\/code> connects directly to an SMTP server from your Python process. You manage SMTP credentials, TLS setup, and per-provider quirks (Gmail app passwords, Outlook modern auth). It is also synchronous only.<\/pee><pee>The Unipile email API is a cloud abstraction: link accounts via OAuth (no SMTP credentials in your code for Gmail\/Outlook), get a single consistent HTTP API for all providers, and Unipile handles transport, token refresh, and retries. The trade-off is that sends route through Unipile&#8217;s infrastructure rather than a direct SMTP connection.<\/pee><\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] -->  <div class=\"upl-faq-item\"><!-- [et_pb_line_break_holder] -->    <button class=\"upl-faq-question\" aria-expanded=\"false\"><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-question-content\"><!-- [et_pb_line_break_holder] -->        <span class=\"upl-faq-number\">04<\/span><!-- [et_pb_line_break_holder] -->        <span class=\"upl-faq-question-text\">Does this work with async\/await in Python?<\/span><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->    <\/button><!-- [et_pb_line_break_holder] -->    <div class=\"upl-faq-answer\"><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-answer-content\"><pee>Yes, but you need an async HTTP client &#8211; the standard <code>requests<\/code> library is synchronous and will block your event loop. Use <code>httpx<\/code> (recommended, drop-in async alternative) or <code>aiohttp<\/code>.<\/pee><div class=\"faq-mini-code\"><code><span class=\"fq-k\">import<\/span><span class=\"fq-w\"> httpx, os, json<\/span><!-- [et_pb_line_break_holder] --><!-- [et_pb_line_break_holder] --><span class=\"fq-k\">async def<\/span><span class=\"fq-w\"> <\/span><span class=\"fq-fn\">send_email_async<\/span><span class=\"fq-w\">(to: <\/span><span class=\"fq-fn\">str<\/span><span class=\"fq-w\">, subject: <\/span><span class=\"fq-fn\">str<\/span><span class=\"fq-w\">, body: <\/span><span class=\"fq-fn\">str<\/span><span class=\"fq-w\">):<\/span><!-- [et_pb_line_break_holder] --><span class=\"fq-w\">    <\/span><span class=\"fq-k\">async with<\/span><span class=\"fq-w\"> httpx.<\/span><span class=\"fq-fn\">AsyncClient<\/span><span class=\"fq-w\">() <\/span><span class=\"fq-k\">as<\/span><span class=\"fq-w\"> client:<\/span><!-- [et_pb_line_break_holder] --><span class=\"fq-w\">        resp = <\/span><span class=\"fq-k\">await<\/span><span class=\"fq-w\"> client.<\/span><span class=\"fq-fn\">post<\/span><span class=\"fq-w\">(<\/span><!-- [et_pb_line_break_holder] --><span class=\"fq-w\">            <\/span><span class=\"fq-fn\">f<\/span><span class=\"fq-s\">'{os.environ[\"UNIPILE_DSN\"]}\/api\/v1\/emails'<\/span><span class=\"fq-w\">,<\/span><!-- [et_pb_line_break_holder] --><span class=\"fq-w\">            headers={<\/span><span class=\"fq-s\">'X-API-KEY'<\/span><span class=\"fq-w\">: os.environ[<\/span><span class=\"fq-s\">'UNIPILE_API_KEY'<\/span><span class=\"fq-w\">]},<\/span><!-- [et_pb_line_break_holder] --><span class=\"fq-w\">            data={<\/span><span class=\"fq-s\">'account_id'<\/span><span class=\"fq-w\">: os.environ[<\/span><span class=\"fq-s\">'UNIPILE_ACCOUNT_ID'<\/span><span class=\"fq-w\">],<\/span><!-- [et_pb_line_break_holder] --><span class=\"fq-w\">                  <\/span><span class=\"fq-s\">'to'<\/span><span class=\"fq-w\">: json.<\/span><span class=\"fq-fn\">dumps<\/span><span class=\"fq-w\">([{<\/span><span class=\"fq-s\">'identifier'<\/span><span class=\"fq-w\">: to}]),<\/span><!-- [et_pb_line_break_holder] --><span class=\"fq-w\">                  <\/span><span class=\"fq-s\">'subject'<\/span><span class=\"fq-w\">: subject, <\/span><span class=\"fq-s\">'body'<\/span><span class=\"fq-w\">: body}<\/span><!-- [et_pb_line_break_holder] --><span class=\"fq-w\">        )<\/span><!-- [et_pb_line_break_holder] --><span class=\"fq-w\">        resp.<\/span><span class=\"fq-fn\">raise_for_status<\/span><span class=\"fq-w\">()<\/span><!-- [et_pb_line_break_holder] --><span class=\"fq-w\">        <\/span><span class=\"fq-k\">return<\/span><span class=\"fq-w\"> resp.<\/span><span class=\"fq-fn\">json<\/span><span class=\"fq-w\">()<\/span><\/code><\/div><\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] -->  <div class=\"upl-faq-item\"><!-- [et_pb_line_break_holder] -->    <button class=\"upl-faq-question\" aria-expanded=\"false\"><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-question-content\"><!-- [et_pb_line_break_holder] -->        <span class=\"upl-faq-number\">05<\/span><!-- [et_pb_line_break_holder] -->        <span class=\"upl-faq-question-text\">How do I send 10,000 emails from Python efficiently?<\/span><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->    <\/button><!-- [et_pb_line_break_holder] -->    <div class=\"upl-faq-answer\"><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-answer-content\"><pee>Use a Celery task queue with a Redis or RabbitMQ broker. Each email becomes a task &#8211; Celery handles concurrency and retries automatically. Limit concurrency per worker to avoid rate limits (typically 5-10 concurrent sends per linked account). For truly high-volume marketing sends (millions\/day), combine Unipile for OAuth-based transactional sends with a dedicated ESP for bulk campaigns.<\/pee><pee>For lighter use cases, <code>concurrent.futures.ThreadPoolExecutor(max_workers=5)<\/code> with the <code>requests<\/code> library is a simpler approach that avoids the Celery overhead.<\/pee><\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] -->  <div class=\"upl-faq-item\"><!-- [et_pb_line_break_holder] -->    <button class=\"upl-faq-question\" aria-expanded=\"false\"><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-question-content\"><!-- [et_pb_line_break_holder] -->        <span class=\"upl-faq-number\">06<\/span><!-- [et_pb_line_break_holder] -->        <span class=\"upl-faq-question-text\">Can I use it with Celery for async task-based sending?<\/span><!-- [et_pb_line_break_holder] -->      <\/div><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg><\/div><!-- [et_pb_line_break_holder] -->    <\/button><!-- [et_pb_line_break_holder] -->    <div class=\"upl-faq-answer\"><!-- [et_pb_line_break_holder] -->      <div class=\"upl-faq-answer-content\"><pee>Yes. Create a Celery task that calls <code>requests.post()<\/code> to the Unipile endpoint. Celery workers are standard synchronous Python processes, so <code>requests<\/code> works perfectly. Use Celery&#8217;s built-in <code>autoretry_for=(requests.exceptions.HTTPError,)<\/code> with <code>max_retries=3<\/code> and <code>default_retry_delay=5<\/code> for automatic retry on transient failures. Combine with <code>Idempotency-Key<\/code> headers to prevent duplicate sends on worker restarts.<\/pee><\/div><!-- [et_pb_line_break_holder] -->    <\/div><!-- [et_pb_line_break_holder] -->  <\/div><!-- [et_pb_line_break_holder] --><\/div><!-- [et_pb_line_break_holder] --><div class=\"upl-faq-cta\"><!-- [et_pb_line_break_holder] -->  <pee class=\"upl-faq-cta-text\">Still have questions? Our team is here to help.<\/pee><!-- [et_pb_line_break_holder] -->  <button class=\"upl-faq-cta-button\" onclick=\"if(window.$crisp){$crisp.push(['do','chat:open'])}\"><span>Talk to an expert<\/span><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><polyline points=\"12 5 19 12 12 19\"\/><\/svg><\/button><!-- [et_pb_line_break_holder] --><\/div><!-- [et_pb_line_break_holder] --><\/div><!-- [et_pb_line_break_holder] --><script type=\"application\/ld+json\"><!-- [et_pb_line_break_holder] -->{<!-- [et_pb_line_break_holder] -->  \"@context\": \"https:\/\/schema.org\",<!-- [et_pb_line_break_holder] -->  \"@type\": \"FAQPage\",<!-- [et_pb_line_break_holder] -->  \"mainEntity\": [<!-- [et_pb_line_break_holder] -->    {\"@type\": \"Question\",\"name\": \"How do I send email in Python without SMTP?\",\"acceptedAnswer\": {\"@type\": \"Answer\",\"text\": \"Use the Unipile unified email API. Install requests, get your API key and DSN from the Unipile dashboard, link a Gmail or Outlook account via OAuth, then POST to \/api\/v1\/emails with your account_id, to, subject, and body. No SMTP server, no port 587, no TLS configuration needed in your Python code.\"}},<!-- [et_pb_line_break_holder] -->    {\"@type\": \"Question\",\"name\": \"Can I use the Unipile email API Python integration with Django, Flask, or FastAPI?\",\"acceptedAnswer\": {\"@type\": \"Answer\",\"text\": \"Yes. In Django, call the API in a view or management command. In Flask, call it server-side in a route handler. In FastAPI, use httpx.AsyncClient inside async endpoints - the synchronous requests library blocks the async event loop.\"}},<!-- [et_pb_line_break_holder] -->    {\"@type\": \"Question\",\"name\": \"What is the difference between smtplib and a unified email API in Python?\",\"acceptedAnswer\": {\"@type\": \"Answer\",\"text\": \"smtplib connects directly to SMTP and requires managing credentials and TLS per provider. The Unipile email API is a cloud abstraction: link accounts via OAuth, use a single HTTP API for all providers, and Unipile handles transport, token refresh, and retries.\"}},<!-- [et_pb_line_break_holder] -->    {\"@type\": \"Question\",\"name\": \"Does the Unipile email API work with Python async\/await?\",\"acceptedAnswer\": {\"@type\": \"Answer\",\"text\": \"Yes, but use httpx.AsyncClient or aiohttp instead of requests, which is synchronous. Use async with httpx.AsyncClient() as client: and await client.post() for non-blocking sends in FastAPI or async Django.\"}},<!-- [et_pb_line_break_holder] -->    {\"@type\": \"Question\",\"name\": \"How do I send 10,000 emails from Python efficiently?\",\"acceptedAnswer\": {\"@type\": \"Answer\",\"text\": \"Use Celery with Redis or RabbitMQ broker. Each email is a task with autoretry on HTTP errors. Limit to 5-10 concurrent sends per linked account. For simpler cases, concurrent.futures.ThreadPoolExecutor(max_workers=5) works without the Celery overhead.\"}},<!-- [et_pb_line_break_holder] -->    {\"@type\": \"Question\",\"name\": \"Can I use the Unipile email API with Celery for Python async task-based sending?\",\"acceptedAnswer\": {\"@type\": \"Answer\",\"text\": \"Yes. Celery workers are synchronous Python processes, so requests works perfectly. Use autoretry_for=(requests.exceptions.HTTPError,) with max_retries=3. Combine with Idempotency-Key headers to prevent duplicate sends on worker restarts.\"}}<!-- [et_pb_line_break_holder] -->  ]<!-- [et_pb_line_break_holder] -->}<!-- [et_pb_line_break_holder] --><\/script><!-- [et_pb_line_break_holder] --><script><!-- [et_pb_line_break_holder] -->(function(){<!-- [et_pb_line_break_holder] -->  function init(){<!-- [et_pb_line_break_holder] -->    document.querySelectorAll('#upl-faq-pyapi .upl-faq-question').forEach(function(btn){<!-- [et_pb_line_break_holder] -->      btn.addEventListener('click', function(){<!-- [et_pb_line_break_holder] -->        var item = btn.closest('.upl-faq-item');<!-- [et_pb_line_break_holder] -->        var isActive = item.classList.contains('active');<!-- [et_pb_line_break_holder] -->        document.querySelectorAll('#upl-faq-pyapi .upl-faq-item').forEach(function(i){<!-- [et_pb_line_break_holder] -->          i.classList.remove('active');<!-- [et_pb_line_break_holder] -->          i.querySelector('.upl-faq-question').setAttribute('aria-expanded','false');<!-- [et_pb_line_break_holder] -->        });<!-- [et_pb_line_break_holder] -->        if(!isActive){ item.classList.add('active'); btn.setAttribute('aria-expanded','true'); }<!-- [et_pb_line_break_holder] -->      });<!-- [et_pb_line_break_holder] -->    });<!-- [et_pb_line_break_holder] -->  }<!-- [et_pb_line_break_holder] -->  if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',init);}else{init();}<!-- [et_pb_line_break_holder] -->})();<!-- [et_pb_line_break_holder] --><\/script>[\/et_pb_code][\/et_pb_column][\/et_pb_row][\/et_pb_section]\n","protected":false},"excerpt":{"rendered":"<p>Python Tutorial How to Send Email via API in Python (Quick Tutorial) Skip the SMTP boilerplate. This guide shows you how to use the Unipile unified email API to send email in Python &#8211; with copy-paste examples for Gmail, Outlook, and IMAP using the requests library. email api python send email api python Gmail \/ [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":278467,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"on","_et_pb_old_content":"","_et_gb_content_width":"","inline_featured_image":false,"footnotes":""},"categories":[37],"tags":[],"post_folder":[],"class_list":["post-278392","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cat-guides"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>How to Send Email via API in Python (Quick Tutorial) - Unipile<\/title>\n<meta name=\"description\" content=\"Learn how to send email via API in Python. Copy-paste examples for Gmail, Outlook &amp; SMTP using the Unipile unified API and requests library.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.unipile.com\/fr\/envoyer-un-e-mail-api-python\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Send Email via API in Python (Quick Tutorial) - Unipile\" \/>\n<meta property=\"og:description\" content=\"Learn how to send email via API in Python. Copy-paste examples for Gmail, Outlook &amp; SMTP using the Unipile unified API and requests library.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.unipile.com\/fr\/envoyer-un-e-mail-api-python\/\" \/>\n<meta property=\"og:site_name\" content=\"Unipile\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/unipilefr\" \/>\n<meta property=\"article:published_time\" content=\"2026-04-27T15:19:42+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-04-28T15:25:47+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.unipile.com\/wp-content\/uploads\/2024\/02\/gmail-3.svg\" \/>\n<meta name=\"author\" content=\"Damien Girardeau\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@UnipileAPI\" \/>\n<meta name=\"twitter:site\" content=\"@UnipileAPI\" \/>\n<meta name=\"twitter:label1\" content=\"\u00c9crit par\" \/>\n\t<meta name=\"twitter:data1\" content=\"Damien Girardeau\" \/>\n\t<meta name=\"twitter:label2\" content=\"Dur\u00e9e de lecture estim\u00e9e\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/send-email-api-python\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/send-email-api-python\\\/\"},\"author\":{\"name\":\"Damien Girardeau\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#\\\/schema\\\/person\\\/a2ac44e22bdc27d497ce8b58716a673e\"},\"headline\":\"How to Send Email via API in Python (Quick Tutorial)\",\"datePublished\":\"2026-04-27T15:19:42+00:00\",\"dateModified\":\"2026-04-28T15:25:47+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/send-email-api-python\\\/\"},\"wordCount\":3808,\"publisher\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/send-email-api-python\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.unipile.com\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/09-send-email-api-python.png\",\"articleSection\":[\"Guides\"],\"inLanguage\":\"fr-FR\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/send-email-api-python\\\/\",\"url\":\"https:\\\/\\\/www.unipile.com\\\/send-email-api-python\\\/\",\"name\":\"How to Send Email via API in Python (Quick Tutorial) - Unipile\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/send-email-api-python\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/send-email-api-python\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.unipile.com\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/09-send-email-api-python.png\",\"datePublished\":\"2026-04-27T15:19:42+00:00\",\"dateModified\":\"2026-04-28T15:25:47+00:00\",\"description\":\"Learn how to send email via API in Python. Copy-paste examples for Gmail, Outlook & SMTP using the Unipile unified API and requests library.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/send-email-api-python\\\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.unipile.com\\\/send-email-api-python\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/send-email-api-python\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.unipile.com\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/09-send-email-api-python.png\",\"contentUrl\":\"https:\\\/\\\/www.unipile.com\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/09-send-email-api-python.png\",\"width\":2400,\"height\":1600,\"caption\":\"Quick Python tutorial with copy-paste examples for Gmail, Outlook and IMAP using the Unipile unified API.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/send-email-api-python\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\\\/\\\/www.unipile.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to Send Email via API in Python (Quick Tutorial)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#website\",\"url\":\"https:\\\/\\\/www.unipile.com\\\/\",\"name\":\"Unipile\",\"description\":\"Integrate Messaging &amp; Email, Connect with Ease via API\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.unipile.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fr-FR\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#organization\",\"name\":\"Unipile\",\"url\":\"https:\\\/\\\/www.unipile.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.unipile.com\\\/wp-content\\\/uploads\\\/2021\\\/05\\\/logo-unipile.png\",\"contentUrl\":\"https:\\\/\\\/www.unipile.com\\\/wp-content\\\/uploads\\\/2021\\\/05\\\/logo-unipile.png\",\"width\":200,\"height\":49,\"caption\":\"Unipile\"},\"image\":{\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/unipilefr\",\"https:\\\/\\\/x.com\\\/UnipileAPI\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/unipile\\\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.unipile.com\\\/#\\\/schema\\\/person\\\/a2ac44e22bdc27d497ce8b58716a673e\",\"name\":\"Damien Girardeau\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/12dd140720736a8db29f540c42a17d2680cd54a04fb26bb7b55423c179b065a9?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/12dd140720736a8db29f540c42a17d2680cd54a04fb26bb7b55423c179b065a9?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/12dd140720736a8db29f540c42a17d2680cd54a04fb26bb7b55423c179b065a9?s=96&d=mm&r=g\",\"caption\":\"Damien Girardeau\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Comment envoyer des e-mails via API en Python (Tutoriel rapide) - Unipile","description":"Apprenez \u00e0 envoyer des e-mails via l'API en Python. Copiez-collez des exemples pour Gmail, Outlook et SMTP en utilisant l'API unifi\u00e9e Unipile et la biblioth\u00e8que requests.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.unipile.com\/fr\/envoyer-un-e-mail-api-python\/","og_locale":"fr_FR","og_type":"article","og_title":"How to Send Email via API in Python (Quick Tutorial) - Unipile","og_description":"Learn how to send email via API in Python. Copy-paste examples for Gmail, Outlook & SMTP using the Unipile unified API and requests library.","og_url":"https:\/\/www.unipile.com\/fr\/envoyer-un-e-mail-api-python\/","og_site_name":"Unipile","article_publisher":"https:\/\/www.facebook.com\/unipilefr","article_published_time":"2026-04-27T15:19:42+00:00","article_modified_time":"2026-04-28T15:25:47+00:00","og_image":[{"url":"https:\/\/www.unipile.com\/wp-content\/uploads\/2024\/02\/gmail-3.svg","type":"","width":"","height":""}],"author":"Damien Girardeau","twitter_card":"summary_large_image","twitter_creator":"@UnipileAPI","twitter_site":"@UnipileAPI","twitter_misc":{"\u00c9crit par":"Damien Girardeau","Dur\u00e9e de lecture estim\u00e9e":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.unipile.com\/send-email-api-python\/#article","isPartOf":{"@id":"https:\/\/www.unipile.com\/send-email-api-python\/"},"author":{"name":"Damien Girardeau","@id":"https:\/\/www.unipile.com\/#\/schema\/person\/a2ac44e22bdc27d497ce8b58716a673e"},"headline":"How to Send Email via API in Python (Quick Tutorial)","datePublished":"2026-04-27T15:19:42+00:00","dateModified":"2026-04-28T15:25:47+00:00","mainEntityOfPage":{"@id":"https:\/\/www.unipile.com\/send-email-api-python\/"},"wordCount":3808,"publisher":{"@id":"https:\/\/www.unipile.com\/#organization"},"image":{"@id":"https:\/\/www.unipile.com\/send-email-api-python\/#primaryimage"},"thumbnailUrl":"https:\/\/www.unipile.com\/wp-content\/uploads\/2026\/04\/09-send-email-api-python.png","articleSection":["Guides"],"inLanguage":"fr-FR"},{"@type":"WebPage","@id":"https:\/\/www.unipile.com\/send-email-api-python\/","url":"https:\/\/www.unipile.com\/send-email-api-python\/","name":"Comment envoyer des e-mails via API en Python (Tutoriel rapide) - Unipile","isPartOf":{"@id":"https:\/\/www.unipile.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.unipile.com\/send-email-api-python\/#primaryimage"},"image":{"@id":"https:\/\/www.unipile.com\/send-email-api-python\/#primaryimage"},"thumbnailUrl":"https:\/\/www.unipile.com\/wp-content\/uploads\/2026\/04\/09-send-email-api-python.png","datePublished":"2026-04-27T15:19:42+00:00","dateModified":"2026-04-28T15:25:47+00:00","description":"Apprenez \u00e0 envoyer des e-mails via l'API en Python. Copiez-collez des exemples pour Gmail, Outlook et SMTP en utilisant l'API unifi\u00e9e Unipile et la biblioth\u00e8que requests.","breadcrumb":{"@id":"https:\/\/www.unipile.com\/send-email-api-python\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.unipile.com\/send-email-api-python\/"]}]},{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/www.unipile.com\/send-email-api-python\/#primaryimage","url":"https:\/\/www.unipile.com\/wp-content\/uploads\/2026\/04\/09-send-email-api-python.png","contentUrl":"https:\/\/www.unipile.com\/wp-content\/uploads\/2026\/04\/09-send-email-api-python.png","width":2400,"height":1600,"caption":"Quick Python tutorial with copy-paste examples for Gmail, Outlook and IMAP using the Unipile unified API."},{"@type":"BreadcrumbList","@id":"https:\/\/www.unipile.com\/send-email-api-python\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.unipile.com\/"},{"@type":"ListItem","position":2,"name":"How to Send Email via API in Python (Quick Tutorial)"}]},{"@type":"WebSite","@id":"https:\/\/www.unipile.com\/#website","url":"https:\/\/www.unipile.com\/","name":"Unipile","description":"Int\u00e9grer la messagerie et l'e-mail, se connecter facilement via l'API","publisher":{"@id":"https:\/\/www.unipile.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.unipile.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fr-FR"},{"@type":"Organization","@id":"https:\/\/www.unipile.com\/#organization","name":"Unipile","url":"https:\/\/www.unipile.com\/","logo":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/www.unipile.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.unipile.com\/wp-content\/uploads\/2021\/05\/logo-unipile.png","contentUrl":"https:\/\/www.unipile.com\/wp-content\/uploads\/2021\/05\/logo-unipile.png","width":200,"height":49,"caption":"Unipile"},"image":{"@id":"https:\/\/www.unipile.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/unipilefr","https:\/\/x.com\/UnipileAPI","https:\/\/www.linkedin.com\/company\/unipile\/"]},{"@type":"Person","@id":"https:\/\/www.unipile.com\/#\/schema\/person\/a2ac44e22bdc27d497ce8b58716a673e","name":"Damien Girardeau","image":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/secure.gravatar.com\/avatar\/12dd140720736a8db29f540c42a17d2680cd54a04fb26bb7b55423c179b065a9?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/12dd140720736a8db29f540c42a17d2680cd54a04fb26bb7b55423c179b065a9?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/12dd140720736a8db29f540c42a17d2680cd54a04fb26bb7b55423c179b065a9?s=96&d=mm&r=g","caption":"Damien Girardeau"}}]}},"_links":{"self":[{"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/posts\/278392","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/comments?post=278392"}],"version-history":[{"count":14,"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/posts\/278392\/revisions"}],"predecessor-version":[{"id":278409,"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/posts\/278392\/revisions\/278409"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/media\/278467"}],"wp:attachment":[{"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/media?parent=278392"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/categories?post=278392"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/tags?post=278392"},{"taxonomy":"post_folder","embeddable":true,"href":"https:\/\/www.unipile.com\/fr\/wp-json\/wp\/v2\/post_folder?post=278392"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}