long smtp_rcpt (SENDSTREAM *stream,ADDRESS *adr,long *error) { char *s,tmp[2*MAILTMPLEN],orcpt[MAILTMPLEN]; while (adr) { /* for each address on the list */ /* clear any former error */ if (adr->error) fs_give ((void **) &adr->error); if (adr->host) { /* ignore group syntax */ /* enforce SMTP limits to protect the buffer */ if (strlen (adr->mailbox) > MAXLOCALPART) { adr->error = cpystr ("501 Recipient name too long"); *error = T; } else if ((strlen (adr->host) > SMTPMAXDOMAIN)) { adr->error = cpystr ("501 Recipient domain too long"); *error = T; } #ifndef RFC2821 /* old code with A-D-L support */ else if (adr->adl && (strlen (adr->adl) > SMTPMAXPATH)) { adr->error = cpystr ("501 Path too long"); *error = T; } #endif else { strcpy (tmp,"TO:<"); /* compose "RCPT TO:<return-path>" */ #ifdef RFC2821 rfc822_cat (tmp,adr->mailbox,NIL); sprintf (tmp + strlen (tmp),"@%s>",adr->host); #else /* old code with A-D-L support */ rfc822_address (tmp,adr); strcat (tmp,">"); #endif /* want notifications */ if (ESMTP.ok && ESMTP.dsn.ok && ESMTP.dsn.want) { /* yes, start with prefix */ strcat (tmp," NOTIFY="); s = tmp + strlen (tmp); if (ESMTP.dsn.notify.failure) strcat (s,"FAILURE,"); if (ESMTP.dsn.notify.delay) strcat (s,"DELAY,"); if (ESMTP.dsn.notify.success) strcat (s,"SUCCESS,"); /* tie off last comma */ if (*s) s[strlen (s) - 1] = '\0'; else strcat (tmp,"NEVER"); if (adr->orcpt.addr) { sprintf (orcpt,"%.498s;%.498s", adr->orcpt.type ? adr->orcpt.type : "rfc822", adr->orcpt.addr); sprintf (tmp + strlen (tmp)," ORCPT=%.500s",orcpt); } } switch (smtp_send (stream,"RCPT",tmp)) { case SMTPOK: /* looks good */ break; case SMTPUNAVAIL: /* mailbox unavailable? */ case SMTPWANTAUTH: /* wants authentication? */ case SMTPWANTAUTH2: if (ESMTP.auth) return T; default: /* other failure */ *error = T; /* note that an error occurred */ adr->error = cpystr (stream->reply); } } } adr = adr->next; /* do any subsequent recipients */ } return NIL; /* no retry called for */ }
int mutt_copy_header (FILE *in, HEADER *h, FILE *out, int flags, const char *prefix) { char buffer[SHORT_STRING]; if (h->env) flags |= (h->env->irt_changed ? CH_UPDATE_IRT : 0) | (h->env->refs_changed ? CH_UPDATE_REFS : 0); if (mutt_copy_hdr (in, out, h->offset, h->content->offset, flags, prefix) == -1) return -1; if (flags & CH_TXTPLAIN) { char chsbuf[SHORT_STRING]; fputs ("MIME-Version: 1.0\n", out); fputs ("Content-Transfer-Encoding: 8bit\n", out); fputs ("Content-Type: text/plain; charset=", out); mutt_canonical_charset (chsbuf, sizeof (chsbuf), Charset ? Charset : "us-ascii"); rfc822_cat(buffer, sizeof(buffer), chsbuf, MimeSpecials); fputs(buffer, out); fputc('\n', out); } if ((flags & CH_UPDATE_IRT) && h->env->in_reply_to) { LIST *listp = h->env->in_reply_to; fputs ("In-Reply-To:", out); for (; listp; listp = listp->next) { fputc (' ', out); fputs (listp->data, out); } fputc ('\n', out); } if ((flags & CH_UPDATE_REFS) && h->env->references) { fputs ("References:", out); mutt_write_references (h->env->references, out, 0); fputc ('\n', out); } if ((flags & CH_UPDATE) && (flags & CH_NOSTATUS) == 0) { if (h->old || h->read) { fputs ("Status: ", out); if (h->read) fputs ("RO", out); else if (h->old) fputc ('O', out); fputc ('\n', out); } if (h->flagged || h->replied) { fputs ("X-Status: ", out); if (h->replied) fputc ('A', out); if (h->flagged) fputc ('F', out); fputc ('\n', out); } } if (flags & CH_UPDATE_LEN && (flags & CH_NOLEN) == 0) { fprintf (out, "Content-Length: " OFF_T_FMT "\n", h->content->length); if (h->lines != 0 || h->content->length == 0) fprintf (out, "Lines: %d\n", h->lines); } if ((flags & CH_NONEWLINE) == 0) { if (flags & CH_PREFIX) fputs(prefix, out); fputc ('\n', out); /* add header terminator */ } if (ferror (out) || feof (out)) return -1; return 0; }
long smtp_mail (SENDSTREAM *stream,char *type,ENVELOPE *env,BODY *body) { RFC822BUFFER buf; char tmp[SENDBUFLEN+1]; long error = NIL; long retry = NIL; buf.f = smtp_soutr; /* initialize buffer */ buf.s = stream->netstream; buf.end = (buf.beg = buf.cur = tmp) + SENDBUFLEN; tmp[SENDBUFLEN] = '\0'; /* must have additional null guard byte */ if (!(env->to || env->cc || env->bcc)) { /* no recipients in request */ smtp_seterror (stream,SMTPHARDERROR,"No recipients specified"); return NIL; } do { /* make sure stream is in good shape */ if (retry) { /* need to retry with authentication? */ NETMBX mb; /* yes, build remote name for authentication */ sprintf (tmp,"{%.200s/smtp%s}<none>", (long) mail_parameters (NIL,GET_TRUSTDNS,NIL) ? ((long) mail_parameters (NIL,GET_SASLUSESPTRNAME,NIL) ? net_remotehost (stream->netstream) : net_host (stream->netstream)) : stream->host, (stream->netstream->dtb == (NETDRIVER *) mail_parameters (NIL,GET_SSLDRIVER,NIL)) ? "/ssl" : ""); mail_valid_net_parse (tmp,&mb); smtp_send (stream,"RSET",NIL); if (!smtp_auth (stream,&mb,tmp)) return NIL; retry = NIL; /* no retry at this point */ } strcpy (tmp,"FROM:<"); /* compose "MAIL FROM:<return-path>" */ #ifdef RFC2821 if (env->return_path && env->return_path->host && !((strlen (env->return_path->mailbox) > SMTPMAXLOCALPART) || (strlen (env->return_path->host) > SMTPMAXDOMAIN))) { rfc822_cat (tmp,env->return_path->mailbox,NIL); sprintf (tmp + strlen (tmp),"@%s",env->return_path->host); } #else /* old code with A-D-L support */ if (env->return_path && env->return_path->host && !((env->return_path->adl && (strlen (env->return_path->adl) > SMTPMAXPATH)) || (strlen (env->return_path->mailbox) > SMTPMAXLOCALPART) || (strlen (env->return_path->host) > SMTPMAXDOMAIN))) rfc822_address (tmp,env->return_path); #endif strcat (tmp,">"); if (ESMTP.ok) { if (ESMTP.eightbit.ok && ESMTP.eightbit.want) strcat (tmp," BODY=8BITMIME"); if (ESMTP.dsn.ok && ESMTP.dsn.want) { strcat (tmp,ESMTP.dsn.full ? " RET=FULL" : " RET=HDRS"); if (ESMTP.dsn.envid) sprintf (tmp + strlen (tmp)," ENVID=%.100s",ESMTP.dsn.envid); } } /* send "MAIL FROM" command */ switch (smtp_send (stream,type,tmp)) { case SMTPUNAVAIL: /* mailbox unavailable? */ case SMTPWANTAUTH: /* wants authentication? */ case SMTPWANTAUTH2: if (ESMTP.auth) retry = T;/* yes, retry with authentication */ case SMTPOK: /* looks good */ break; default: /* other failure */ smtp_send (stream,"RSET",NIL); return NIL; } /* negotiate the recipients */ if (!retry && env->to) retry = smtp_rcpt (stream,env->to,&error); if (!retry && env->cc) retry = smtp_rcpt (stream,env->cc,&error); if (!retry && env->bcc) retry = smtp_rcpt (stream,env->bcc,&error); if (!retry && error) { /* any recipients failed? */ smtp_send (stream,"RSET",NIL); smtp_seterror (stream,SMTPHARDERROR,"One or more recipients failed"); return NIL; } } while (retry); /* negotiate data command */ if (!(smtp_send (stream,"DATA",NIL) == SMTPREADY)) { smtp_send (stream,"RSET",NIL); return NIL; } /* send message data */ if (!rfc822_output_full (&buf,env,body, ESMTP.eightbit.ok && ESMTP.eightbit.want)) { smtp_fake (stream,"SMTP connection broken (message data)"); return NIL; /* can't do much else here */ } /* send trailing dot */ if (smtp_send (stream,".",NIL) != SMTPOK) { smtp_send (stream,"RSET",NIL); return NIL; } return LONGT; }