1"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1101],{11101:(e,t,s)=>{s.r(t),s.d(t,{default:()=>h});var i=s(37876),l=s(14232),n=s(12559),r=s(15648),a=s(65457),o=s(25430);let c=e=>{let t=e.startsWith("<")&&e.endsWith(">"),s=(t?e.slice(1,-1):e).trim().toLowerCase();return{raw:e,scheme:s.startsWith("https:")?"https":s.startsWith("http:")?"http":s.startsWith("mailto:")?"mailto":"other",bracketed:t}},h=()=>{let[e,t]=(0,l.useState)(""),[s,h]=(0,l.useState)(null),u=s?.check??null;return(0,i.jsx)(r.xP,{outputLabel:"Result",controls:(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(r.D0,{label:"Headers",hint:"Paste the List-Unsubscribe and List-Unsubscribe-Post lines, or the full raw headers; the tool finds them. Parsed in your browser, sent nowhere.",children:(0,i.jsx)(r.fs,{rows:9,value:e,onChange:e=>t(e.target.value),placeholder:"List-Unsubscribe: <https://example.com/unsub?u=123>,\n <mailto:[email protected]>\nList-Unsubscribe-Post: List-Unsubscribe=One-Click",spellCheck:!1,className:(0,n.AH)({fontSize:"12px"}),style:{fontFamily:r.iP}})}),(0,i.jsx)(r.jn,{type:"button",onClick:()=>{let t=(0,o.QG)(e),s=(0,o.Jj)(t,"List-Unsubscribe"),i=(0,o.Jj)(t,"List-Unsubscribe-Post");if(!s)return void h({check:null,missing:!0});h({check:((e,t)=>{let s=[],i=[],l=(e=>{let t=[],s=0,i="";for(let l of e)"<"===l&&(s+=1),">"===l&&(s=Math.max(0,s-1)),","===l&&0===s?(t.push(i),i=""):i+=l;return t.push(i),t.map(e=>e.trim()).filter(Boolean)})(e).map(c);for(let e of(l.length||s.push("The List-Unsubscribe header has no URIs in it."),l))e.bracketed||s.push(`"${e.raw}" is not wrapped in angle brackets. RFC 2369 requires <...> around each URI.`),"http"===e.scheme&&s.push(`"${e.raw}" uses http. One-click unsubscribe requires https.`),"other"===e.scheme&&s.push(`"${e.raw}" is neither an https URL nor a mailto address.`);l.length>2&&i.push(`${l.length} URIs found. RFC 2369 allows more, but mailbox providers only use the first https and first mailto entry; extra entries are noise.`);let n=l.some(e=>"https"===e.scheme&&e.bracketed);l.some(e=>"mailto"===e.scheme&&e.bracketed)||i.push("No mailto entry. Not required for one-click, but some receivers still use it, and it is the fallback when the https endpoint is down.");let r=t?.trim()??null,a="List-Unsubscribe=One-Click"===r,o=null!==r&&"list-unsubscribe=one-click"===r.toLowerCase();return null===r?s.push("No List-Unsubscribe-Post header. Without it the https link is not one-click: Gmail and Yahoo will not show the native unsubscribe button for bulk mail."):o?a||i.push(`List-Unsubscribe-Post is "${r}". Receivers generally accept this casing, but the RFC 8058 value is "List-Unsubscribe=One-Click" verbatim.`):s.push(`List-Unsubscribe-Post is "${r}". RFC 8058 requires exactly "List-Unsubscribe=One-Click".`),null===r||n||s.push("List-Unsubscribe-Post is set but there is no https URI to POST to. One-click needs both."),{entries:l,problems:s,warnings:i,oneClick:n&&o}})(s,i),missing:!1})},disabled:!e.trim(),children:"Check one-click unsubscribe"}),(0,i.jsx)("p",{className:(0,n.AH)({fontSize:"12px",color:"#6B645C",mt:"10px",lineHeight:"1.5"}),children:"This checks syntax only. It never sends a POST to the endpoint, because a real POST would unsubscribe the recipient whose headers you pasted."})]}),output:s?s.missing?(0,i.jsxs)("div",{children:[(0,i.jsx)(a.qs,{status:"fail",children:"missing"}),(0,i.jsx)("p",{className:(0,n.AH)({fontSize:"13.5px",lineHeight:"1.6",mt:"10px",color:"#1C1815"}),children:"No List-Unsubscribe header found. For bulk mail to Gmail and Yahoo this is a compliance failure on its own: both require the header, and its absence also costs you the native unsubscribe button that keeps frustrated recipients from reaching for the spam button instead."})]}):u?(0,i.jsxs)("div",{children:[(0,i.jsxs)("div",{className:(0,n.AH)({display:"flex",alignItems:"center",gap:"10px",mb:"12px"}),children:[(0,i.jsx)(a.qs,{status:u.oneClick?u.problems.length?"warn":"pass":"fail",children:u.oneClick?"one-click OK":"not one-click"}),(0,i.jsx)("span",{className:(0,n.AH)({fontSize:"13px",color:"#6B645C"}),children:u.oneClick?u.problems.length?"One-click will work, but the header has problems worth fixing.":"Header syntax satisfies RFC 8058.":"This message does not qualify for one-click unsubscribe."})]}),u.entries.map((e,t)=>
1(0,i.jsx)(a.u6,{label:`URI ${t+1} (${e.scheme})`,mono:!0,children:e.raw},t)),u.problems.length>0&&(0,i.jsx)("div",{className:(0,n.AH)({mt:"14px"}),children:u.problems.map((e,t)=>(0,i.jsxs)("div",{className:(0,n.AH)({display:"flex",gap:"8px",alignItems:"flex-start",fontSize:"13px",lineHeight:"1.55",mb:"8px"}),children:[(0,i.jsx)("span",{style:{flexShrink:0,marginTop:"1px"},children:(0,i.jsx)(a.qs,{status:"fail",children:"fix"})}),(0,i.jsx)("span",{children:e})]},t))}),u.warnings.length>0&&(0,i.jsx)("div",{className:(0,n.AH)({mt:u.problems.length?"4px":"14px"}),children:u.warnings.map((e,t)=>(0,i.jsxs)("div",{className:(0,n.AH)({display:"flex",gap:"8px",alignItems:"flex-start",fontSize:"13px",lineHeight:"1.55",mb:"8px"}),children:[(0,i.jsx)("span",{style:{flexShrink:0,marginTop:"1px"},children:(0,i.jsx)(a.qs,{status:"warn",children:"note"})}),(0,i.jsx)("span",{children:e})]},t))}),u.oneClick&&(0,i.jsx)("p",{className:(0,n.AH)({fontSize:"12.5px",color:"#6B645C",mt:"10px",lineHeight:"1.55"}),children:"Still on you to verify: the endpoint must accept the POST and process it without asking the recipient to log in or confirm. This tool cannot test that without unsubscribing someone."})]}):null:(0,i.jsx)(a.rM,{children:"Paste headers to check whether the message qualifies for one-click unsubscribe under RFC 8058, which Gmail and Yahoo require for bulk senders."})})}},25430:(e,t,s)=>{s.d(t,{H8:()=>a,JW:()=>n,Jj:()=>l,QG:()=>i});let i=e=>{let t=[];for(let s of(e=>{let t=e.replace(/\r\n/g,"\n").replace(/\r/g,"\n").split("\n"),s=[];for(let e of t){if(""===e.trim()&&s.length)break;/^[ \t]/.test(e)&&s.length?s[s.length-1]+=" "+e.trim():""!==e.trim()&&s.push(e)}return s})(e)){let e=s.indexOf(":");e<=0||t.push({name:s.slice(0,e).trim(),value:s.slice(e+1).trim()})}return t},l=(e,t)=>e.find(e=>e.name.toLowerCase()===t.toLowerCase())?.value??null,n=(e,t)=>e.filter(e=>e.name.toLowerCase()===t.toLowerCase()).map(e=>e.value),r=e=>{let t=e.lastIndexOf(";"),s=t>=0?e.slice(t+1).trim():null,i=s?Date.parse(s):NaN;return{from:e.match(/(?:^|\s)from\s+([^\s();]+)/i)?.[1]??null,by:e.match(/(?:^|\s)by\s+([^\s();]+)/i)?.[1]??null,date:s,timestamp:Number.isNaN(i)?null:i,raw:e}},a=e=>{let t=i(e),s=n(t,"Received").map(r).reverse().map((e,t,s)=>{let i=t>0?s[t-1].timestamp:null,l=null!==i&&null!==e.timestamp?Math.round((e.timestamp-i)/1e3):null;return{...e,delaySeconds:l}}),l=s.filter(e=>null!==e.timestamp),a=l.length>=2?Math.round((l[l.length-1].timestamp-l[0].timestamp)/1e3):null;return{headers:t,hops:s,auth:(e=>{let t=[],s=new Set;for(let i of e)for(let e of Array.from(i.matchAll(/\b(spf|dkim|dmarc|compauth)=([a-zA-Z0-9_-]+)\s*(\([^)]*\))?/g))){let i=e[1].toLowerCase();s.has(i)||(s.add(i),t.push({method:i,result:e[2].toLowerCase(),detail:e[3]?e[3].slice(1,-1).trim():null}))}return t})(n(t,"Authentication-Results")),totalDelaySeconds:a}}},59225:(e,t,s)=>{s.d(t,{Z:()=>l,x:()=>i});let i=e=>{let t;try{t=new URLSearchParams(e.startsWith("?")?e.slice(1):e)}catch{return{value:null,selector:null}}let s=(t.get("domain")??t.get("email")??"").trim(),i=s.length>0&&s.length<=253&&/^[a-zA-Z0-9._@+-]+$/.test(s)&&s.includes(".")?s:null,l=(t.get("selector")??"").trim();return{value:i,selector:l.length>0&&l.length<=63&&/^[a-zA-Z0-9._-]+$/.test(l)?l:null}},l=(e,t)=>{let s=e.trim();if(!s)return"";let i=new URLSearchParams;return i.set("domain",s),t&&t.trim()&&i.set("selector",t.trim()),`?${i.toString()}`}},65457:(e,t,s)=>{s.d(t,{FM:()=>p,gh:()=>u,qs:()=>c,rM:()=>m,u6:()=>h});var i=s(37876),l=s(14232),n=s(12559),r=s(15648),a=s(59225);let o={pass:{bg:"#DCF5EC",fg:"#0E8A6D"},warn:{bg:"#FDF0DC",fg:"#B45309"},fail:{bg:"#FDE4E1",fg:"#C0392B"},info:{bg:"#EDE7FD",fg:"#6D3FE0"}},c=({status:e,children:t})=>(0,i.jsx)("span",{className:(0,n.AH)({display:"inline-block",fontSize:"11.5px",fontWeight:600,letterSpacing:"0.04em",textTransform:"uppercase",borderRadius:"999px",px:"10px",py:"3px",whiteSpace:"nowrap"}),style:{background:o[e].bg,color:o[e].fg},children:t}),h=({label:e,children:t,mono:s})=>(0,i.jsxs)("div",{className:(0,n.AH)({display:"grid",gridTemplateColumns:{base:"1fr",customSm:"150px 1fr"},gap:{base:"2px",customSm:"16px"},py:"10px",borderBottom:"1px solid #E4E0DA",_last:{borderBottom:"none"},fontSize:"13.5px",lineHeight:"1.55"}),children:[(0,i.jsx)("span",{className:(0,n.AH)({color:"#6B645C",fontSize:"11.5px",letterSpacing:"0.06em",textTransform:"uppercase",pt:"2px"}),style:{fontFamily:r.iP},children:e}),(0,i.jsx)("span",{className:(0,n.AH)({color:"#1C1815",wordBreak:"break-word",minWidth:0}),style:s?{fontFamily:r.iP,fontSize:"12.5px"}:void 0,children:t})]}),u=({value:e})=>(0,i.jsx)("pre",{className:(0,n.AH)({fontSize:"12px",lineHeight:"1.6",color:"#1C1815",bg:"#F5F3F0",border:"1px solid #E4E0DA",borderRadius:"8px",p:"12px",whiteSpace:"pre-wrap",wordBreak:"break-all",mt:"8px"}),style:{fontFamily:r.iP},children:e}),p=({label:e,placeholder:t,buttonLabel:s,hint:o,onCheck:c,children:h,extraParam:u})=>{let[p,m]=(0,l.useState)(""),[d,b]=(0,l.useState)(!1),[x,f]=(0,l.useState)(""),g=async e=>{b(!0),f("");try{await c(e);{let t=(0,a.Z)(e,u??null);window.history.replaceState(null,"",`${window.location.pathname}${t}`)}}catch(e){f(e instanceof Error&&e.message?e.message:"Lookup failed. Check the value and try again.")}finally{b(!1)}},k=async e=>{e.preventDefault(),p.trim()&&!d&&await g(p)},w=(0,l.useRef)(!1);return(0,l.useEffect)(()=>
1{if(w.current)return;w.current=!0;let{value:e}=(0,a.x)(window.location.search);e&&(m(e),g(e))},[]),(0,i.jsxs)("form",{onSubmit:k,children:[(0,i.jsx)(r.D0,{label:e,hint:o,children:(0,i.jsx)(r.ks,{placeholder:t,value:p,onChange:e=>m(e.target.value),autoCapitalize:"none",autoCorrect:"off",spellCheck:!1})}),h,(0,i.jsx)(r.jn,{type:"submit",disabled:d||!p.trim(),children:d?"Checking...":s}),x?(0,i.jsx)("p",{className:(0,n.AH)({fontSize:"13px",color:"#C0392B",mt:"10px"}),children:x}):null]})},m=({children:e})=>(0,i.jsx)("p",{className:(0,n.AH)({fontSize:"13.5px",color:"#A39C93",lineHeight:"1.6"}),children:e})}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.