+static
+void
+handle_sendfrom(char **vec, int *vecp, char *draft, const char *auth_svc) {
+ const char *addr, *host;
+ const char *message;
+
+ /* Extract address and host from From: header line in draft. */
+ if (get_from_header_info(draft, &addr, &host, &message) != OK) {
+ adios(draft, "%s", message);
+ }
+
+ /* Merge in any address or host specific switches to post(1) from profile. */
+ merge_profile_entry(addr, host, vec, vecp);
+ free((void *) host);
+ free((void *) addr);
+
+ vec[*vecp] = NULL;
+
+ {
+ char **vp;
+
+ for (vp = vec; *vp; ++vp) {
+ if (strcmp(*vp, "xoauth2") == 0) {
+#ifdef OAUTH_SUPPORT
+ if (setup_oauth_params(vec, vecp, auth_svc, &message) != OK) {
+ adios(NULL, "%s", message);
+ }
+ break;
+#else
+ NMH_UNUSED(auth_svc);
+ adios(NULL, "send built without OAUTH_SUPPORT, "
+ "so -saslmech xoauth2 is not supported");
+#endif /* OAUTH_SUPPORT */
+ }
+ }
+ }
+}
+
+
+#ifdef OAUTH_SUPPORT
+/*
+ * For XOAUTH2, append profile entries so post can do the heavy lifting
+ */
+static int
+setup_oauth_params(char *vec[], int *vecp, const char *auth_svc,
+ const char **message) {
+ const char *saslmech = NULL, *user = NULL;
+ mh_oauth_service_info svc;
+ char errbuf[256];
+ int i;
+
+ /* Make sure we have all the information we need. */
+ for (i = 1; i < *vecp; ++i) {
+ /* Don't support abbreviated switches, to avoid collisions in the
+ future if new ones are added. */
+ if (! strcmp(vec[i-1], "-saslmech")) {
+ saslmech = vec[i];
+ } else if (! strcmp(vec[i-1], "-user")) {
+ user = vec[i];
+ } else if (! strcmp(vec[i-1], "-authservice")) {
+ auth_svc = vec[i];
+ }
+ }
+
+ if (auth_svc == NULL) {
+ if (saslmech && ! strcasecmp(saslmech, "xoauth2")) {
+ *message = "must specify -authservice with -saslmech xoauth2";
+ return NOTOK;
+ }
+ } else {
+ if (user == NULL) {
+ *message = "must specify -user with -saslmech xoauth2";
+ return NOTOK;
+ }
+
+ if (saslmech && ! strcasecmp(saslmech, "xoauth2")) {
+ if (! mh_oauth_get_service_info(auth_svc, &svc, errbuf,
+ sizeof(errbuf)))
+ adios(NULL, "Unable to retrieve oauth profile entries: %s",
+ errbuf);
+
+ vec[(*vecp)++] = mh_xstrdup("-authservice");
+ vec[(*vecp)++] = mh_xstrdup(auth_svc);
+ vec[(*vecp)++] = mh_xstrdup("-oauthcredfile");
+ vec[(*vecp)++] = mh_xstrdup(mh_oauth_cred_fn(auth_svc));
+ vec[(*vecp)++] = mh_xstrdup("-oauthclientid");
+ vec[(*vecp)++] = getcpy(svc.client_id);
+ vec[(*vecp)++] = mh_xstrdup("-oauthclientsecret");
+ vec[(*vecp)++] = getcpy(svc.client_secret);
+ vec[(*vecp)++] = mh_xstrdup("-oauthauthendpoint");
+ vec[(*vecp)++] = getcpy(svc.auth_endpoint);
+ vec[(*vecp)++] = mh_xstrdup("-oauthredirect");
+ vec[(*vecp)++] = getcpy(svc.redirect_uri);
+ vec[(*vecp)++] = mh_xstrdup("-oauthtokenendpoint");
+ vec[(*vecp)++] = getcpy(svc.token_endpoint);
+ vec[(*vecp)++] = mh_xstrdup("-oauthscope");
+ vec[(*vecp)++] = getcpy(svc.scope);
+ }
+ }
+
+ return 0;
+}
+#endif /* OAUTH_SUPPORT */
+
+
+/*
+ * Extract user and domain from From: header line in draft.
+ */
+static