[{"data":1,"prerenderedAt":2015},["ShallowReactive",2],{"navigation_docs":3,"-sending-smtp":191,"-sending-smtp-surround":2010},[4,31,67,103,129,155,175],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":30},"Getting started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,15,20,25],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Quick start","\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F3.quick-start","i-lucide-play",{"title":26,"path":27,"stem":28,"icon":29},"Agent Skill","\u002Fgetting-started\u002Fagent-skill","1.getting-started\u002F4.agent-skill","i-lucide-sparkles",false,{"title":32,"icon":33,"path":34,"stem":35,"children":36,"page":30},"Authoring","i-lucide-pen-line","\u002Fauthoring","2.authoring",[37,42,47,52,57,62],{"title":38,"path":39,"stem":40,"icon":41},"Comark syntax","\u002Fauthoring\u002Fcomark-syntax","2.authoring\u002F1.comark-syntax","i-lucide-file-code",{"title":43,"path":44,"stem":45,"icon":46},"Frontmatter","\u002Fauthoring\u002Ffrontmatter","2.authoring\u002F2.frontmatter","i-lucide-heading",{"title":48,"path":49,"stem":50,"icon":51},"Modules","\u002Fauthoring\u002Fmodules","2.authoring\u002F3.modules","i-lucide-blocks",{"title":53,"path":54,"stem":55,"icon":56},"Merge tags and bindings","\u002Fauthoring\u002Fmerge-tags-and-bindings","2.authoring\u002F4.merge-tags-and-bindings","i-lucide-braces",{"title":58,"path":59,"stem":60,"icon":61},"Actions and spans","\u002Fauthoring\u002Factions-and-spans","2.authoring\u002F5.actions-and-spans","i-lucide-mouse-pointer-click",{"title":63,"path":64,"stem":65,"icon":66},"Compile errors","\u002Fauthoring\u002Fcompile-errors","2.authoring\u002F6.compile-errors","i-lucide-circle-alert",{"title":68,"icon":69,"path":70,"stem":71,"children":72,"page":30},"Rendering","i-lucide-layout-template","\u002Frendering","3.rendering",[73,78,83,88,93,98],{"title":74,"path":75,"stem":76,"icon":77},"Families and streams","\u002Frendering\u002Ffamilies-and-streams","3.rendering\u002F1.families-and-streams","i-lucide-users",{"title":79,"path":80,"stem":81,"icon":82},"Themes","\u002Frendering\u002Fthemes","3.rendering\u002F2.themes","i-lucide-palette",{"title":84,"path":85,"stem":86,"icon":87},"Config and the renderer","\u002Frendering\u002Fconfig-and-renderer","3.rendering\u002F3.config-and-renderer","i-lucide-settings",{"title":89,"path":90,"stem":91,"icon":92},"Layout and spacing","\u002Frendering\u002Flayout-and-spacing","3.rendering\u002F4.layout-and-spacing","i-lucide-ruler",{"title":94,"path":95,"stem":96,"icon":97},"HTML output","\u002Frendering\u002Fhtml-output","3.rendering\u002F5.html-output","i-lucide-code-xml",{"title":99,"path":100,"stem":101,"icon":102},"Plain text","\u002Frendering\u002Fplain-text","3.rendering\u002F6.plain-text","i-lucide-file-text",{"title":104,"icon":105,"path":106,"stem":107,"children":108,"page":30},"Sending","i-lucide-send","\u002Fsending","4.sending",[109,114,119,124],{"title":110,"path":111,"stem":112,"icon":113},"Message and MIME","\u002Fsending\u002Fmessage-and-mime","4.sending\u002F1.message-and-mime","i-lucide-mail",{"title":115,"path":116,"stem":117,"icon":118},"Router and streams","\u002Fsending\u002Frouter-and-streams","4.sending\u002F2.router-and-streams","i-lucide-route",{"title":120,"path":121,"stem":122,"icon":123},"SMTP","\u002Fsending\u002Fsmtp","4.sending\u002F3.smtp","i-lucide-server",{"title":125,"path":126,"stem":127,"icon":128},"Maps","\u002Fsending\u002Fmaps","4.sending\u002F4.maps","i-lucide-map",{"title":130,"icon":131,"path":132,"stem":133,"children":134,"page":30},"Tooling","i-lucide-wrench","\u002Ftooling","5.tooling",[135,140,145,150],{"title":136,"path":137,"stem":138,"icon":139},"The lttr CLI","\u002Ftooling\u002Fcli","5.tooling\u002F1.cli","i-lucide-terminal",{"title":141,"path":142,"stem":143,"icon":144},"Live preview","\u002Ftooling\u002Flive-preview","5.tooling\u002F2.live-preview","i-lucide-eye",{"title":146,"path":147,"stem":148,"icon":149},"Screenshots","\u002Ftooling\u002Fscreenshots","5.tooling\u002F3.screenshots","i-lucide-camera",{"title":151,"path":152,"stem":153,"icon":154},"Goldens and testing","\u002Ftooling\u002Fgoldens-and-testing","5.tooling\u002F4.goldens-and-testing","i-lucide-flask-conical",{"title":156,"icon":157,"path":158,"stem":159,"children":160,"page":30},"Guides","i-lucide-book-open","\u002Fguides","6.guides",[161,166,170],{"title":162,"path":163,"stem":164,"icon":165},"The Quiet example","\u002Fguides\u002Fthe-quiet-example","6.guides\u002F1.the-quiet-example","i-lucide-mail-open",{"title":167,"path":168,"stem":169,"icon":82},"Your own family and theme","\u002Fguides\u002Fyour-own-family-and-theme","6.guides\u002F2.your-own-family-and-theme",{"title":171,"path":172,"stem":173,"icon":174},"Releasing","\u002Fguides\u002Freleasing","6.guides\u002F3.releasing","i-lucide-tag",{"title":176,"icon":177,"path":178,"stem":179,"children":180,"page":30},"Reference","i-lucide-library","\u002Freference","7.reference",[181,186],{"title":182,"path":183,"stem":184,"icon":185},"API reference","\u002Freference\u002Fapi-reference","7.reference\u002F1.api-reference","i-lucide-list-tree",{"title":187,"path":188,"stem":189,"icon":190},"Gallery","\u002Freference\u002Fgallery","7.reference\u002F2.gallery","i-lucide-images",{"id":192,"title":120,"body":193,"description":2003,"extension":2004,"links":2005,"meta":2006,"navigation":2007,"path":121,"seo":2008,"stem":122,"__hash__":2009},"docs\u002F4.sending\u002F3.smtp.md",{"type":194,"value":195,"toc":1997},"minimark",[196,219,224,318,415,871,875,880,979,992,996,1028,1919,1971,1975,1993],[197,198,199,203,204,210,211,214,215,218],"p",{},[200,201,202],"code",{},"lttr.SMTP"," is a ",[205,206,207],"a",{"href":116},[200,208,209],{},"Sender"," that delivers each message over its own SMTP session — no connection pooling, no batching, one ",[200,212,213],{},"net\u002Fsmtp"," conversation per ",[200,216,217],{},"Send"," call.",[220,221,223],"h2",{"id":222},"configure-it","Configure it",[225,226,231],"pre",{"className":227,"code":228,"language":229,"meta":230,"style":230},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","type SMTP struct {\n    Addr    string\n    Auth    smtp.Auth\n    Headers map[string]string\n    Now     func() time.Time\n}\n","go","",[200,232,233,252,263,278,295,312],{"__ignoreMap":230},[234,235,238,242,246,249],"span",{"class":236,"line":237},"line",1,[234,239,241],{"class":240},"sMK4o","type",[234,243,245],{"class":244},"sBMFI"," SMTP",[234,247,248],{"class":240}," struct",[234,250,251],{"class":240}," {\n",[234,253,255,259],{"class":236,"line":254},2,[234,256,258],{"class":257},"sTEyZ","    Addr    ",[234,260,262],{"class":261},"spNyl","string\n",[234,264,266,269,272,275],{"class":236,"line":265},3,[234,267,268],{"class":257},"    Auth    ",[234,270,271],{"class":244},"smtp",[234,273,274],{"class":240},".",[234,276,277],{"class":244},"Auth\n",[234,279,281,284,287,290,293],{"class":236,"line":280},4,[234,282,283],{"class":257},"    Headers ",[234,285,286],{"class":240},"map[",[234,288,289],{"class":261},"string",[234,291,292],{"class":240},"]",[234,294,262],{"class":261},[234,296,298,301,304,307,309],{"class":236,"line":297},5,[234,299,300],{"class":257},"    Now     ",[234,302,303],{"class":240},"func()",[234,305,306],{"class":244}," time",[234,308,274],{"class":240},[234,310,311],{"class":244},"Time\n",[234,313,315],{"class":236,"line":314},6,[234,316,317],{"class":240},"}\n",[319,320,321,338,362,396],"ul",{},[322,323,324,330,331,334,335,274],"li",{},[325,326,327],"strong",{},[200,328,329],{},"Addr"," is the server's ",[200,332,333],{},"host:port",", e.g. ",[200,336,337],{},"\"smtp.example.com:587\"",[322,339,340,345,346,349,350,353,354,357,358,361],{},[325,341,342],{},[200,343,344],{},"Auth"," authenticates the session (",[200,347,348],{},"smtp.PlainAuth",", ",[200,351,352],{},"smtp.CRAMMD5Auth",", or a custom ",[200,355,356],{},"smtp.Auth","). Leave it ",[200,359,360],{},"nil"," to send without authentication.",[322,363,364,369,370,372,373,376,377,380,381,384,385,388,389,392,393,395],{},[325,365,366],{},[200,367,368],{},"Headers"," are added to every message this ",[200,371,120],{}," sends — the natural place for a provider-specific header like ",[200,374,375],{},"X-SES-CONFIGURATION-SET"," or ",[200,378,379],{},"X-Mailgun-Tag",". They go through the same checks as ",[200,382,383],{},"Message.SetHeader"," (reserved names, CR\u002FLF\u002FNUL, printable ASCII), applied to a ",[325,386,387],{},"copy"," of the message, so the same ",[200,390,391],{},"*Message"," sent through two different ",[200,394,120],{}," values never cross-contaminates their headers.",[322,397,398,403,404,407,408,410,411,414],{},[325,399,400],{},[200,401,402],{},"Now"," stamps the ",[200,405,406],{},"Date"," header; ",[200,409,360],{}," means ",[200,412,413],{},"time.Now",". Set it in tests for deterministic output.",[225,416,419],{"className":227,"code":417,"filename":418,"language":229,"meta":230,"style":230},"package main\n\nimport (\n    \"context\"\n    \"fmt\"\n    \"net\u002Fmail\"\n\n    \"github.com\u002Fsulv-io\u002Flttr\"\n)\n\nfunc main() {\n    s := &lttr.SMTP{\n        Addr: \"smtp.example.com:587\",\n        Headers: map[string]string{\n            \"X-SES-CONFIGURATION-SET\": \"transactional\",\n        },\n    }\n\n    m := &lttr.Message{\n        From:    mail.Address{Name: \"CaribHubs\", Address: \"orders@caribhubs.com\"},\n        To:      mail.Address{Name: \"Keisha Browne\", Address: \"keisha@example.com\"},\n        Subject: \"Your order is on its way\",\n        HTML:    \"\u003Cp>On its way.\u003C\u002Fp>\",\n        Text:    \"On its way.\",\n    }\n\n    if err := s.Send(context.Background(), m); err != nil {\n        fmt.Println(\"send failed:\", err)\n    }\n}\n","main.go",[200,420,421,429,435,444,455,464,473,478,488,494,499,514,536,558,577,598,604,610,615,634,683,726,743,760,777,782,787,834,861,866],{"__ignoreMap":230},[234,422,423,426],{"class":236,"line":237},[234,424,425],{"class":240},"package",[234,427,428],{"class":244}," main\n",[234,430,431],{"class":236,"line":254},[234,432,434],{"emptyLinePlaceholder":433},true,"\n",[234,436,437,441],{"class":236,"line":265},[234,438,440],{"class":439},"s7zQu","import",[234,442,443],{"class":240}," (\n",[234,445,446,449,452],{"class":236,"line":280},[234,447,448],{"class":240},"    \"",[234,450,451],{"class":244},"context",[234,453,454],{"class":240},"\"\n",[234,456,457,459,462],{"class":236,"line":297},[234,458,448],{"class":240},[234,460,461],{"class":244},"fmt",[234,463,454],{"class":240},[234,465,466,468,471],{"class":236,"line":314},[234,467,448],{"class":240},[234,469,470],{"class":244},"net\u002Fmail",[234,472,454],{"class":240},[234,474,476],{"class":236,"line":475},7,[234,477,434],{"emptyLinePlaceholder":433},[234,479,481,483,486],{"class":236,"line":480},8,[234,482,448],{"class":240},[234,484,485],{"class":244},"github.com\u002Fsulv-io\u002Flttr",[234,487,454],{"class":240},[234,489,491],{"class":236,"line":490},9,[234,492,493],{"class":240},")\n",[234,495,497],{"class":236,"line":496},10,[234,498,434],{"emptyLinePlaceholder":433},[234,500,502,505,509,512],{"class":236,"line":501},11,[234,503,504],{"class":240},"func",[234,506,508],{"class":507},"s2Zo4"," main",[234,510,511],{"class":240},"()",[234,513,251],{"class":240},[234,515,517,520,523,526,529,531,533],{"class":236,"line":516},12,[234,518,519],{"class":257},"    s ",[234,521,522],{"class":240},":=",[234,524,525],{"class":240}," &",[234,527,528],{"class":244},"lttr",[234,530,274],{"class":240},[234,532,120],{"class":244},[234,534,535],{"class":240},"{\n",[234,537,539,542,545,548,552,555],{"class":236,"line":538},13,[234,540,541],{"class":257},"        Addr",[234,543,544],{"class":240},":",[234,546,547],{"class":240}," \"",[234,549,551],{"class":550},"sfazB","smtp.example.com:587",[234,553,554],{"class":240},"\"",[234,556,557],{"class":240},",\n",[234,559,561,564,566,569,571,573,575],{"class":236,"line":560},14,[234,562,563],{"class":257},"        Headers",[234,565,544],{"class":240},[234,567,568],{"class":240}," map[",[234,570,289],{"class":261},[234,572,292],{"class":240},[234,574,289],{"class":261},[234,576,535],{"class":240},[234,578,580,583,585,587,589,591,594,596],{"class":236,"line":579},15,[234,581,582],{"class":240},"            \"",[234,584,375],{"class":550},[234,586,554],{"class":240},[234,588,544],{"class":240},[234,590,547],{"class":240},[234,592,593],{"class":550},"transactional",[234,595,554],{"class":240},[234,597,557],{"class":240},[234,599,601],{"class":236,"line":600},16,[234,602,603],{"class":240},"        },\n",[234,605,607],{"class":236,"line":606},17,[234,608,609],{"class":240},"    }\n",[234,611,613],{"class":236,"line":612},18,[234,614,434],{"emptyLinePlaceholder":433},[234,616,618,621,623,625,627,629,632],{"class":236,"line":617},19,[234,619,620],{"class":257},"    m ",[234,622,522],{"class":240},[234,624,525],{"class":240},[234,626,528],{"class":244},[234,628,274],{"class":240},[234,630,631],{"class":244},"Message",[234,633,535],{"class":240},[234,635,637,640,642,645,647,650,653,656,658,660,663,665,668,671,673,675,678,680],{"class":236,"line":636},20,[234,638,639],{"class":257},"        From",[234,641,544],{"class":240},[234,643,644],{"class":244},"    mail",[234,646,274],{"class":240},[234,648,649],{"class":244},"Address",[234,651,652],{"class":240},"{",[234,654,655],{"class":257},"Name",[234,657,544],{"class":240},[234,659,547],{"class":240},[234,661,662],{"class":550},"CaribHubs",[234,664,554],{"class":240},[234,666,667],{"class":240},",",[234,669,670],{"class":257}," Address",[234,672,544],{"class":240},[234,674,547],{"class":240},[234,676,677],{"class":550},"orders@caribhubs.com",[234,679,554],{"class":240},[234,681,682],{"class":240},"},\n",[234,684,686,689,691,694,696,698,700,702,704,706,709,711,713,715,717,719,722,724],{"class":236,"line":685},21,[234,687,688],{"class":257},"        To",[234,690,544],{"class":240},[234,692,693],{"class":244},"      mail",[234,695,274],{"class":240},[234,697,649],{"class":244},[234,699,652],{"class":240},[234,701,655],{"class":257},[234,703,544],{"class":240},[234,705,547],{"class":240},[234,707,708],{"class":550},"Keisha Browne",[234,710,554],{"class":240},[234,712,667],{"class":240},[234,714,670],{"class":257},[234,716,544],{"class":240},[234,718,547],{"class":240},[234,720,721],{"class":550},"keisha@example.com",[234,723,554],{"class":240},[234,725,682],{"class":240},[234,727,729,732,734,736,739,741],{"class":236,"line":728},22,[234,730,731],{"class":257},"        Subject",[234,733,544],{"class":240},[234,735,547],{"class":240},[234,737,738],{"class":550},"Your order is on its way",[234,740,554],{"class":240},[234,742,557],{"class":240},[234,744,746,749,751,753,756,758],{"class":236,"line":745},23,[234,747,748],{"class":257},"        HTML",[234,750,544],{"class":240},[234,752,448],{"class":240},[234,754,755],{"class":550},"\u003Cp>On its way.\u003C\u002Fp>",[234,757,554],{"class":240},[234,759,557],{"class":240},[234,761,763,766,768,770,773,775],{"class":236,"line":762},24,[234,764,765],{"class":257},"        Text",[234,767,544],{"class":240},[234,769,448],{"class":240},[234,771,772],{"class":550},"On its way.",[234,774,554],{"class":240},[234,776,557],{"class":240},[234,778,780],{"class":236,"line":779},25,[234,781,609],{"class":240},[234,783,785],{"class":236,"line":784},26,[234,786,434],{"emptyLinePlaceholder":433},[234,788,790,793,796,798,801,803,805,808,810,812,815,818,821,824,826,829,832],{"class":236,"line":789},27,[234,791,792],{"class":439},"    if",[234,794,795],{"class":257}," err ",[234,797,522],{"class":240},[234,799,800],{"class":257}," s",[234,802,274],{"class":240},[234,804,217],{"class":507},[234,806,807],{"class":240},"(",[234,809,451],{"class":257},[234,811,274],{"class":240},[234,813,814],{"class":507},"Background",[234,816,817],{"class":240},"(),",[234,819,820],{"class":257}," m",[234,822,823],{"class":240},");",[234,825,795],{"class":257},[234,827,828],{"class":240},"!=",[234,830,831],{"class":240}," nil",[234,833,251],{"class":240},[234,835,837,840,842,845,847,849,852,854,856,859],{"class":236,"line":836},28,[234,838,839],{"class":257},"        fmt",[234,841,274],{"class":240},[234,843,844],{"class":507},"Println",[234,846,807],{"class":240},[234,848,554],{"class":240},[234,850,851],{"class":550},"send failed:",[234,853,554],{"class":240},[234,855,667],{"class":240},[234,857,858],{"class":257}," err",[234,860,493],{"class":240},[234,862,864],{"class":236,"line":863},29,[234,865,609],{"class":240},[234,867,869],{"class":236,"line":868},30,[234,870,317],{"class":240},[220,872,874],{"id":873},"follow-one-session","Follow one session",[197,876,877,879],{},[200,878,217],{}," runs a fixed sequence per call:",[881,882,883,898,912,917,934,951,963],"ol",{},[322,884,885,886,889,890,893,894,897],{},"Clone ",[200,887,888],{},"m",", add ",[200,891,892],{},"s.Headers"," to the copy, and serialise it with ",[200,895,896],{},"MIME"," — before any network connection is made, so a message that cannot be encoded never opens a socket.",[322,899,900,901,903,904,907,908,911],{},"Split the host out of ",[200,902,329],{}," and dial it (",[200,905,906],{},"net.Dialer.DialContext",", so ",[200,909,910],{},"ctx"," governs the dial too).",[322,913,914,274],{},[200,915,916],{},"EHLO localhost",[322,918,919,922,923,926,927,930,931,933],{},[325,920,921],{},"STARTTLS"," if the server advertises the extension: ",[200,924,925],{},"tls.Config{ServerName: host, MinVersion: tls.VersionTLS12}",", where ",[200,928,929],{},"host"," is the host parsed out of ",[200,932,329],{}," — the certificate is checked against the server you asked for, not whatever the server claims to be.",[322,935,936,939,940,943,944,946,947,950],{},[325,937,938],{},"AUTH",", only if ",[200,941,942],{},"s.Auth"," is set. If it is set but the server does not offer the ",[200,945,938],{}," extension, that is an error (",[200,948,949],{},"auth is configured but the server does not offer it",") — configured credentials the server never asked for fail loudly rather than silently sending unauthenticated.",[322,952,953,349,956,349,959,962],{},[200,954,955],{},"MAIL FROM:\u003C{m.From.Address}>",[200,957,958],{},"RCPT TO:\u003C{m.To.Address}>",[200,960,961],{},"DATA",", then the serialised message.",[322,964,965,968,969,971,972,974,975,978],{},[325,966,967],{},"QUIT"," after ",[200,970,961],{}," succeeds. A failed ",[200,973,967],{}," is deliberately ignored: the server already accepted the message, so surfacing the error would make a caller who retries on error send it twice. The connection is torn down by a deferred ",[200,976,977],{},"Close"," either way.",[197,980,981,982,984,985,988,989,274],{},"Cancelling ",[200,983,910],{}," at any point aborts the dial or unblocks whatever read or write the session is waiting on (",[200,986,987],{},"context.AfterFunc"," sets a past deadline on the connection), and the returned error wraps ",[200,990,991],{},"ctx.Err()",[220,993,995],{"id":994},"test-it-with-a-fake-server","Test it with a fake server",[197,997,998,1000,1001,1004,1005,1007,1008,1011,1012,1014,1015,349,1017,349,1020,349,1023,349,1025,1027],{},[200,999,217],{}," needs nothing more than a ",[200,1002,1003],{},"net.Listener"," that speaks enough ESMTP to satisfy ",[200,1006,213],{},": ",[200,1009,1010],{},"EHLO",", optionally ",[200,1013,921],{}," and ",[200,1016,938],{},[200,1018,1019],{},"MAIL",[200,1021,1022],{},"RCPT",[200,1024,961],{},[200,1026,967],{},". No real network access or mail server is needed.",[225,1029,1032],{"className":227,"code":1030,"filename":1031,"language":229,"meta":230,"style":230},"\u002F\u002F A minimal in-process ESMTP server: enough for net\u002Fsmtp to complete a\n\u002F\u002F session against, recording what the client sent. The repo's own tests\n\u002F\u002F (smtp_test.go, using the fakeSMTP helper in smtp_fake_test.go) build a\n\u002F\u002F reusable version of this and also cover a stalled greeting, a rejected\n\u002F\u002F verb, a dropped QUIT, and STARTTLS\u002FAUTH failures.\nfunc TestSMTPSendsOverPlainText(t *testing.T) {\n    ln, err := net.Listen(\"tcp\", \"127.0.0.1:0\")\n    if err != nil {\n        t.Fatal(err)\n    }\n    defer ln.Close()\n\n    var got struct{ from, rcpt string; data []byte }\n    go func() {\n        conn, err := ln.Accept()\n        if err != nil {\n            return\n        }\n        defer conn.Close()\n        tc := textproto.NewConn(conn)\n        tc.PrintfLine(\"220 fake ESMTP\")\n        for {\n            line, err := tc.ReadLine()\n            if err != nil {\n                return\n            }\n            verb, arg, _ := strings.Cut(line, \" \")\n            switch strings.ToUpper(verb) {\n            case \"EHLO\", \"HELO\":\n                tc.PrintfLine(\"250 fake\")\n            case \"MAIL\":\n                got.from = arg\n                tc.PrintfLine(\"250 ok\")\n            case \"RCPT\":\n                got.rcpt = arg\n                tc.PrintfLine(\"250 ok\")\n            case \"DATA\":\n                tc.PrintfLine(\"354 go ahead\")\n                \u002F\u002F read until the lone \".\" line, undo dot-stuffing, store got.data\n                tc.PrintfLine(\"250 queued\")\n            case \"QUIT\":\n                tc.PrintfLine(\"221 bye\")\n                return\n            }\n        }\n    }()\n\n    s := &lttr.SMTP{Addr: ln.Addr().String(), Now: func() time.Time { return fixedDate }}\n    m := &lttr.Message{ \u002F* From, To, Subject, HTML, Text *\u002F }\n\n    if err := s.Send(context.Background(), m); err != nil {\n        t.Fatal(err)\n    }\n    if !strings.Contains(got.from, \"orders@caribhubs.com\") {\n        t.Errorf(\"MAIL FROM = %q\", got.from)\n    }\n}\n","smtp_test.go",[200,1033,1034,1040,1045,1050,1055,1060,1089,1128,1140,1157,1161,1176,1180,1216,1226,1246,1259,1264,1269,1283,1305,1326,1333,1354,1367,1372,1377,1414,1435,1458,1478,1491,1508,1528,1541,1555,1574,1587,1607,1613,1633,1646,1666,1671,1676,1681,1687,1692,1753,1775,1780,1817,1832,1837,1875,1909,1914],{"__ignoreMap":230},[234,1035,1036],{"class":236,"line":237},[234,1037,1039],{"class":1038},"sHwdD","\u002F\u002F A minimal in-process ESMTP server: enough for net\u002Fsmtp to complete a\n",[234,1041,1042],{"class":236,"line":254},[234,1043,1044],{"class":1038},"\u002F\u002F session against, recording what the client sent. The repo's own tests\n",[234,1046,1047],{"class":236,"line":265},[234,1048,1049],{"class":1038},"\u002F\u002F (smtp_test.go, using the fakeSMTP helper in smtp_fake_test.go) build a\n",[234,1051,1052],{"class":236,"line":280},[234,1053,1054],{"class":1038},"\u002F\u002F reusable version of this and also cover a stalled greeting, a rejected\n",[234,1056,1057],{"class":236,"line":297},[234,1058,1059],{"class":1038},"\u002F\u002F verb, a dropped QUIT, and STARTTLS\u002FAUTH failures.\n",[234,1061,1062,1064,1067,1069,1073,1076,1079,1081,1084,1087],{"class":236,"line":314},[234,1063,504],{"class":240},[234,1065,1066],{"class":507}," TestSMTPSendsOverPlainText",[234,1068,807],{"class":240},[234,1070,1072],{"class":1071},"sHdIc","t",[234,1074,1075],{"class":240}," *",[234,1077,1078],{"class":244},"testing",[234,1080,274],{"class":240},[234,1082,1083],{"class":244},"T",[234,1085,1086],{"class":240},")",[234,1088,251],{"class":240},[234,1090,1091,1094,1096,1098,1100,1103,1105,1108,1110,1112,1115,1117,1119,1121,1124,1126],{"class":236,"line":475},[234,1092,1093],{"class":257},"    ln",[234,1095,667],{"class":240},[234,1097,795],{"class":257},[234,1099,522],{"class":240},[234,1101,1102],{"class":257}," net",[234,1104,274],{"class":240},[234,1106,1107],{"class":507},"Listen",[234,1109,807],{"class":240},[234,1111,554],{"class":240},[234,1113,1114],{"class":550},"tcp",[234,1116,554],{"class":240},[234,1118,667],{"class":240},[234,1120,547],{"class":240},[234,1122,1123],{"class":550},"127.0.0.1:0",[234,1125,554],{"class":240},[234,1127,493],{"class":240},[234,1129,1130,1132,1134,1136,1138],{"class":236,"line":480},[234,1131,792],{"class":439},[234,1133,795],{"class":257},[234,1135,828],{"class":240},[234,1137,831],{"class":240},[234,1139,251],{"class":240},[234,1141,1142,1145,1147,1150,1152,1155],{"class":236,"line":490},[234,1143,1144],{"class":257},"        t",[234,1146,274],{"class":240},[234,1148,1149],{"class":507},"Fatal",[234,1151,807],{"class":240},[234,1153,1154],{"class":257},"err",[234,1156,493],{"class":240},[234,1158,1159],{"class":236,"line":496},[234,1160,609],{"class":240},[234,1162,1163,1166,1169,1171,1173],{"class":236,"line":501},[234,1164,1165],{"class":439},"    defer",[234,1167,1168],{"class":257}," ln",[234,1170,274],{"class":240},[234,1172,977],{"class":507},[234,1174,1175],{"class":240},"()\n",[234,1177,1178],{"class":236,"line":516},[234,1179,434],{"emptyLinePlaceholder":433},[234,1181,1182,1185,1188,1191,1194,1196,1199,1201,1204,1207,1210,1213],{"class":236,"line":538},[234,1183,1184],{"class":240},"    var",[234,1186,1187],{"class":257}," got ",[234,1189,1190],{"class":240},"struct{",[234,1192,1193],{"class":257}," from",[234,1195,667],{"class":240},[234,1197,1198],{"class":257}," rcpt ",[234,1200,289],{"class":261},[234,1202,1203],{"class":240},";",[234,1205,1206],{"class":257}," data ",[234,1208,1209],{"class":240},"[]",[234,1211,1212],{"class":261},"byte",[234,1214,1215],{"class":240}," }\n",[234,1217,1218,1221,1224],{"class":236,"line":560},[234,1219,1220],{"class":439},"    go",[234,1222,1223],{"class":240}," func()",[234,1225,251],{"class":240},[234,1227,1228,1231,1233,1235,1237,1239,1241,1244],{"class":236,"line":579},[234,1229,1230],{"class":257},"        conn",[234,1232,667],{"class":240},[234,1234,795],{"class":257},[234,1236,522],{"class":240},[234,1238,1168],{"class":257},[234,1240,274],{"class":240},[234,1242,1243],{"class":507},"Accept",[234,1245,1175],{"class":240},[234,1247,1248,1251,1253,1255,1257],{"class":236,"line":600},[234,1249,1250],{"class":439},"        if",[234,1252,795],{"class":257},[234,1254,828],{"class":240},[234,1256,831],{"class":240},[234,1258,251],{"class":240},[234,1260,1261],{"class":236,"line":606},[234,1262,1263],{"class":439},"            return\n",[234,1265,1266],{"class":236,"line":612},[234,1267,1268],{"class":240},"        }\n",[234,1270,1271,1274,1277,1279,1281],{"class":236,"line":617},[234,1272,1273],{"class":439},"        defer",[234,1275,1276],{"class":257}," conn",[234,1278,274],{"class":240},[234,1280,977],{"class":507},[234,1282,1175],{"class":240},[234,1284,1285,1288,1290,1293,1295,1298,1300,1303],{"class":236,"line":636},[234,1286,1287],{"class":257},"        tc ",[234,1289,522],{"class":240},[234,1291,1292],{"class":257}," textproto",[234,1294,274],{"class":240},[234,1296,1297],{"class":507},"NewConn",[234,1299,807],{"class":240},[234,1301,1302],{"class":257},"conn",[234,1304,493],{"class":240},[234,1306,1307,1310,1312,1315,1317,1319,1322,1324],{"class":236,"line":685},[234,1308,1309],{"class":257},"        tc",[234,1311,274],{"class":240},[234,1313,1314],{"class":507},"PrintfLine",[234,1316,807],{"class":240},[234,1318,554],{"class":240},[234,1320,1321],{"class":550},"220 fake ESMTP",[234,1323,554],{"class":240},[234,1325,493],{"class":240},[234,1327,1328,1331],{"class":236,"line":728},[234,1329,1330],{"class":439},"        for",[234,1332,251],{"class":240},[234,1334,1335,1338,1340,1342,1344,1347,1349,1352],{"class":236,"line":745},[234,1336,1337],{"class":257},"            line",[234,1339,667],{"class":240},[234,1341,795],{"class":257},[234,1343,522],{"class":240},[234,1345,1346],{"class":257}," tc",[234,1348,274],{"class":240},[234,1350,1351],{"class":507},"ReadLine",[234,1353,1175],{"class":240},[234,1355,1356,1359,1361,1363,1365],{"class":236,"line":762},[234,1357,1358],{"class":439},"            if",[234,1360,795],{"class":257},[234,1362,828],{"class":240},[234,1364,831],{"class":240},[234,1366,251],{"class":240},[234,1368,1369],{"class":236,"line":779},[234,1370,1371],{"class":439},"                return\n",[234,1373,1374],{"class":236,"line":784},[234,1375,1376],{"class":240},"            }\n",[234,1378,1379,1382,1384,1387,1389,1392,1394,1397,1399,1402,1404,1406,1408,1410,1412],{"class":236,"line":789},[234,1380,1381],{"class":257},"            verb",[234,1383,667],{"class":240},[234,1385,1386],{"class":257}," arg",[234,1388,667],{"class":240},[234,1390,1391],{"class":257}," _ ",[234,1393,522],{"class":240},[234,1395,1396],{"class":257}," strings",[234,1398,274],{"class":240},[234,1400,1401],{"class":507},"Cut",[234,1403,807],{"class":240},[234,1405,236],{"class":257},[234,1407,667],{"class":240},[234,1409,547],{"class":240},[234,1411,547],{"class":240},[234,1413,493],{"class":240},[234,1415,1416,1419,1421,1423,1426,1428,1431,1433],{"class":236,"line":836},[234,1417,1418],{"class":439},"            switch",[234,1420,1396],{"class":257},[234,1422,274],{"class":240},[234,1424,1425],{"class":507},"ToUpper",[234,1427,807],{"class":240},[234,1429,1430],{"class":257},"verb",[234,1432,1086],{"class":240},[234,1434,251],{"class":240},[234,1436,1437,1440,1442,1444,1446,1448,1450,1453,1455],{"class":236,"line":863},[234,1438,1439],{"class":439},"            case",[234,1441,547],{"class":240},[234,1443,1010],{"class":550},[234,1445,554],{"class":240},[234,1447,667],{"class":240},[234,1449,547],{"class":240},[234,1451,1452],{"class":550},"HELO",[234,1454,554],{"class":240},[234,1456,1457],{"class":240},":\n",[234,1459,1460,1463,1465,1467,1469,1471,1474,1476],{"class":236,"line":868},[234,1461,1462],{"class":257},"                tc",[234,1464,274],{"class":240},[234,1466,1314],{"class":507},[234,1468,807],{"class":240},[234,1470,554],{"class":240},[234,1472,1473],{"class":550},"250 fake",[234,1475,554],{"class":240},[234,1477,493],{"class":240},[234,1479,1481,1483,1485,1487,1489],{"class":236,"line":1480},31,[234,1482,1439],{"class":439},[234,1484,547],{"class":240},[234,1486,1019],{"class":550},[234,1488,554],{"class":240},[234,1490,1457],{"class":240},[234,1492,1494,1497,1499,1502,1505],{"class":236,"line":1493},32,[234,1495,1496],{"class":257},"                got",[234,1498,274],{"class":240},[234,1500,1501],{"class":257},"from ",[234,1503,1504],{"class":240},"=",[234,1506,1507],{"class":257}," arg\n",[234,1509,1511,1513,1515,1517,1519,1521,1524,1526],{"class":236,"line":1510},33,[234,1512,1462],{"class":257},[234,1514,274],{"class":240},[234,1516,1314],{"class":507},[234,1518,807],{"class":240},[234,1520,554],{"class":240},[234,1522,1523],{"class":550},"250 ok",[234,1525,554],{"class":240},[234,1527,493],{"class":240},[234,1529,1531,1533,1535,1537,1539],{"class":236,"line":1530},34,[234,1532,1439],{"class":439},[234,1534,547],{"class":240},[234,1536,1022],{"class":550},[234,1538,554],{"class":240},[234,1540,1457],{"class":240},[234,1542,1544,1546,1548,1551,1553],{"class":236,"line":1543},35,[234,1545,1496],{"class":257},[234,1547,274],{"class":240},[234,1549,1550],{"class":257},"rcpt ",[234,1552,1504],{"class":240},[234,1554,1507],{"class":257},[234,1556,1558,1560,1562,1564,1566,1568,1570,1572],{"class":236,"line":1557},36,[234,1559,1462],{"class":257},[234,1561,274],{"class":240},[234,1563,1314],{"class":507},[234,1565,807],{"class":240},[234,1567,554],{"class":240},[234,1569,1523],{"class":550},[234,1571,554],{"class":240},[234,1573,493],{"class":240},[234,1575,1577,1579,1581,1583,1585],{"class":236,"line":1576},37,[234,1578,1439],{"class":439},[234,1580,547],{"class":240},[234,1582,961],{"class":550},[234,1584,554],{"class":240},[234,1586,1457],{"class":240},[234,1588,1590,1592,1594,1596,1598,1600,1603,1605],{"class":236,"line":1589},38,[234,1591,1462],{"class":257},[234,1593,274],{"class":240},[234,1595,1314],{"class":507},[234,1597,807],{"class":240},[234,1599,554],{"class":240},[234,1601,1602],{"class":550},"354 go ahead",[234,1604,554],{"class":240},[234,1606,493],{"class":240},[234,1608,1610],{"class":236,"line":1609},39,[234,1611,1612],{"class":1038},"                \u002F\u002F read until the lone \".\" line, undo dot-stuffing, store got.data\n",[234,1614,1616,1618,1620,1622,1624,1626,1629,1631],{"class":236,"line":1615},40,[234,1617,1462],{"class":257},[234,1619,274],{"class":240},[234,1621,1314],{"class":507},[234,1623,807],{"class":240},[234,1625,554],{"class":240},[234,1627,1628],{"class":550},"250 queued",[234,1630,554],{"class":240},[234,1632,493],{"class":240},[234,1634,1636,1638,1640,1642,1644],{"class":236,"line":1635},41,[234,1637,1439],{"class":439},[234,1639,547],{"class":240},[234,1641,967],{"class":550},[234,1643,554],{"class":240},[234,1645,1457],{"class":240},[234,1647,1649,1651,1653,1655,1657,1659,1662,1664],{"class":236,"line":1648},42,[234,1650,1462],{"class":257},[234,1652,274],{"class":240},[234,1654,1314],{"class":507},[234,1656,807],{"class":240},[234,1658,554],{"class":240},[234,1660,1661],{"class":550},"221 bye",[234,1663,554],{"class":240},[234,1665,493],{"class":240},[234,1667,1669],{"class":236,"line":1668},43,[234,1670,1371],{"class":439},[234,1672,1674],{"class":236,"line":1673},44,[234,1675,1376],{"class":240},[234,1677,1679],{"class":236,"line":1678},45,[234,1680,1268],{"class":240},[234,1682,1684],{"class":236,"line":1683},46,[234,1685,1686],{"class":240},"    }()\n",[234,1688,1690],{"class":236,"line":1689},47,[234,1691,434],{"emptyLinePlaceholder":433},[234,1693,1695,1697,1699,1701,1703,1705,1707,1709,1711,1713,1715,1717,1719,1722,1725,1727,1730,1732,1734,1736,1738,1741,1744,1747,1750],{"class":236,"line":1694},48,[234,1696,519],{"class":257},[234,1698,522],{"class":240},[234,1700,525],{"class":240},[234,1702,528],{"class":244},[234,1704,274],{"class":240},[234,1706,120],{"class":244},[234,1708,652],{"class":240},[234,1710,329],{"class":257},[234,1712,544],{"class":240},[234,1714,1168],{"class":257},[234,1716,274],{"class":240},[234,1718,329],{"class":507},[234,1720,1721],{"class":240},"().",[234,1723,1724],{"class":507},"String",[234,1726,817],{"class":240},[234,1728,1729],{"class":257}," Now",[234,1731,544],{"class":240},[234,1733,1223],{"class":240},[234,1735,306],{"class":244},[234,1737,274],{"class":240},[234,1739,1740],{"class":244},"Time",[234,1742,1743],{"class":240}," {",[234,1745,1746],{"class":439}," return",[234,1748,1749],{"class":257}," fixedDate ",[234,1751,1752],{"class":240},"}}\n",[234,1754,1756,1758,1760,1762,1764,1766,1768,1770,1773],{"class":236,"line":1755},49,[234,1757,620],{"class":257},[234,1759,522],{"class":240},[234,1761,525],{"class":240},[234,1763,528],{"class":244},[234,1765,274],{"class":240},[234,1767,631],{"class":244},[234,1769,652],{"class":240},[234,1771,1772],{"class":1038}," \u002F* From, To, Subject, HTML, Text *\u002F",[234,1774,1215],{"class":240},[234,1776,1778],{"class":236,"line":1777},50,[234,1779,434],{"emptyLinePlaceholder":433},[234,1781,1783,1785,1787,1789,1791,1793,1795,1797,1799,1801,1803,1805,1807,1809,1811,1813,1815],{"class":236,"line":1782},51,[234,1784,792],{"class":439},[234,1786,795],{"class":257},[234,1788,522],{"class":240},[234,1790,800],{"class":257},[234,1792,274],{"class":240},[234,1794,217],{"class":507},[234,1796,807],{"class":240},[234,1798,451],{"class":257},[234,1800,274],{"class":240},[234,1802,814],{"class":507},[234,1804,817],{"class":240},[234,1806,820],{"class":257},[234,1808,823],{"class":240},[234,1810,795],{"class":257},[234,1812,828],{"class":240},[234,1814,831],{"class":240},[234,1816,251],{"class":240},[234,1818,1820,1822,1824,1826,1828,1830],{"class":236,"line":1819},52,[234,1821,1144],{"class":257},[234,1823,274],{"class":240},[234,1825,1149],{"class":507},[234,1827,807],{"class":240},[234,1829,1154],{"class":257},[234,1831,493],{"class":240},[234,1833,1835],{"class":236,"line":1834},53,[234,1836,609],{"class":240},[234,1838,1840,1842,1845,1848,1850,1853,1855,1858,1860,1863,1865,1867,1869,1871,1873],{"class":236,"line":1839},54,[234,1841,792],{"class":439},[234,1843,1844],{"class":240}," !",[234,1846,1847],{"class":257},"strings",[234,1849,274],{"class":240},[234,1851,1852],{"class":507},"Contains",[234,1854,807],{"class":240},[234,1856,1857],{"class":257},"got",[234,1859,274],{"class":240},[234,1861,1862],{"class":257},"from",[234,1864,667],{"class":240},[234,1866,547],{"class":240},[234,1868,677],{"class":550},[234,1870,554],{"class":240},[234,1872,1086],{"class":240},[234,1874,251],{"class":240},[234,1876,1878,1880,1882,1885,1887,1889,1892,1896,1898,1900,1903,1905,1907],{"class":236,"line":1877},55,[234,1879,1144],{"class":257},[234,1881,274],{"class":240},[234,1883,1884],{"class":507},"Errorf",[234,1886,807],{"class":240},[234,1888,554],{"class":240},[234,1890,1891],{"class":550},"MAIL FROM = ",[234,1893,1895],{"class":1894},"swJcz","%q",[234,1897,554],{"class":240},[234,1899,667],{"class":240},[234,1901,1902],{"class":257}," got",[234,1904,274],{"class":240},[234,1906,1862],{"class":257},[234,1908,493],{"class":240},[234,1910,1912],{"class":236,"line":1911},56,[234,1913,609],{"class":240},[234,1915,1917],{"class":236,"line":1916},57,[234,1918,317],{"class":240},[197,1920,1921,1922,1924,1925,1927,1928,1931,1932,1935,1936,1939,1940,376,1942,1944,1945,1947,1948,1950,1951,1954,1955,1957,1958,1960,1961,1963,1964,1967,1968,274],{},"The pattern that matters: run the fake server's ",[200,1923,1243],{},"\u002Fread loop in a goroutine, answer each verb with the SMTP status line ",[200,1926,213],{}," expects, and assert on what it recorded rather than trying to intercept a real connection. ",[200,1929,1930],{},"s.Addr = ln.Addr().String()"," points ",[200,1933,1934],{},"SMTP.Send"," at ",[200,1937,1938],{},"127.0.0.1:{random port}",", so the test never touches the network outside the process. To exercise ",[200,1941,921],{},[200,1943,938],{}," failures, advertise the extension in the ",[200,1946,1010],{}," reply (or don't) and answer (or don't) accordingly — the repo's own tests do exactly this: ",[200,1949,1031],{}," holds the individual ",[200,1952,1953],{},"Test*"," functions (a stalled greeting, a rejected verb, a dropped ",[200,1956,967],{},", an ",[200,1959,938],{}," mismatch, a failed ",[200,1962,921],{}," handshake, and more), all built on the reusable ",[200,1965,1966],{},"fakeSMTP"," helper in ",[200,1969,1970],{},"smtp_fake_test.go",[220,1972,1974],{"id":1973},"next-steps","Next steps",[319,1976,1977,1988],{},[322,1978,1979,1981,1982,1984,1985,1987],{},[205,1980,115],{"href":116}," for picking ",[200,1983,120],{}," (or another ",[200,1986,209],{},") per stream.",[322,1989,1990,1992],{},[205,1991,151],{"href":152}," for testing your own templates end to end.",[1994,1995,1996],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}",{"title":230,"searchDepth":254,"depth":254,"links":1998},[1999,2000,2001,2002],{"id":222,"depth":254,"text":223},{"id":873,"depth":254,"text":874},{"id":994,"depth":254,"text":995},{"id":1973,"depth":254,"text":1974},"The one Sender the library ships, one session per message, and how to test it without a real mail server.","md",null,{},{"icon":123},{"title":120,"description":2003},"td3a3SsCmAoqrZg2Wqr_pEJubteIHq2O1NMiGjdidMg",[2011,2013],{"title":115,"path":116,"stem":117,"description":2012,"icon":118,"children":-1},"Route a rendered Message to the right Sender, with the internal-mail and suppression checks Render cannot make for you.",{"title":125,"path":126,"stem":127,"description":2014,"icon":128,"children":-1},"Build a Mapbox Static Images API URL, fetch the bytes, and keep the access token out of the email and out of your errors.",1790309827953]