hinokichi77
@hinokichi77

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

functions CORSエラーの解決方法(onCall)質問

経緯

Vue.js + Firebase functionsでお問い合わせフォームを作成する
VuejsとFirebaseでメール送信機能を実装する
を参考にfunctionsのnodemailerを自分のアプリに実装しようとしています。
CORSエラーについて下記記事などを参考にしながら解決に取り組んでいますが、まだ解決できないので、ヒントを頂けたらと思い投稿しました、よろしくお願いいたします!
CORSエラーメッセージ(始終変化無し)
2020-07-16 (7).png
functions実行部分

index.js
const functions = require('firebase-functions');

const nodemailer = require("nodemailer");

const gmailEmail = functions.config().gmail.email;

const gmailPassword = functions.config().gmail.password;


// 送信に使用するメールサーバーの設定 環境変数 オーナーと別アカウント
const mailTransport = nodemailer.createTransport({
  service: "gmail",
  auth: {
    user: gmailEmail,
    pass: gmailPassword
  }
});

// 管理者用のメールテンプレート→uresMail text
const noticeMail = data => {
  return `${data.title}締め切り1日前です。

TODO:
${data.title}

詳細はこちらから
todoapp-8da1b.firebaseapp.com
`;
};

exports.sendMail = functions.https.onCall((data, context) => {
  // メール設定userMail
  let userMail = {
    from: gmailEmail,
    to: data.userMail,//userEmail
    subject: `${data.title}の締切1日前です`,//todoTitle
    text: noticeMail(data)
  };
  mailTransport.sendMail(userMail, (err, info) => {
    if (err) {
        return console.log(err)
    }
    return console.log('success')
  })
});
});

// メールテンプレート→uresMail text
const NearDeadlineTodo = data => {
  return `${data.title}締め切り1日前です。

TODO:
${data.title}

詳細はこちらから
todoapp-8da1b.firebaseapp.com
`;
};

exports.sendMail = functions.https.onCall((data, context) => {
  // メール設定userMail
  let userMail = {
    from: gmailEmail,//hinokichi
    to: data.userMail,//userEmail
    subject: `${data.title}の締切1日前です`,//todoTitle
    text: noticeMail(data)
  };
  mailTransport.sendMail(userMail, (err, info) => {
    if (err) {
        return console.log(err)
    }
    return console.log('success')
  })
});

試したこと

↓記事参照しましたが、すでにonCallを使用済みです
FirebaseのCloud FunctionsでCORSが~とかAccess-Control-Allow-Originが~と言われたらこれ

sendMailに使用するメールサーバーはfirebaseプロジェクトのオーナーと異なります。(環境変数で設定済み)
念のためメールサーバーアカウントにもCloudFunctionsをGoogleCloudPlatformコンソールより追加済み

firebase functions:config:set gmail.email="送信元アドレス" gmail.password="アカウントパスワード"

ブラウザーコンソールのエラーメッセージのURLをクリックすると
2020-07-19.png

このワードでググった記事↓の通り、コンソールの権限メンバー追加済み
Firebase functionsで 403 error "Your client does not have permission to get URL /** from this server" となった場合の解決策
2020-07-16 (9).png

corsの対応、以下記事(両記事onRequest使用)
Webサイトから CloudFunctions の実行と躓いたところ
Cloud Functions for Firebase でCORSを許可する方法

送信に使用するメールアカウントがオーナーと別だからかもしれないと、以下を試しましたが、変化無しです
1firebaseプロジェクトオーナーと同じアドレスを環境変数に入力
2$firebase deploy --only functions
3$npm run build→firebase deploy
エラーメッセージに変化無し
4メールサーバー元に戻す
45サブ垢メールのセキュリティーのアクティビティを確認していなかったので承認
6デプロイ
→エラーメッセージ変化無し

念のためimportもスタンダードな形で書き直しましたが、変化なしです。
アプリから関数を呼び出す 公式を参考
main.tsから直接importしない→変化無し
2020-07-18 (7).png
2020-07-18 (8).png

0

1Answer

詳しいところは調べてませんが、ブラウザのエラーは、CORSまわりのヘッダーがFunctionsからのレスポンスに不足していることによるものだと思います。

Same Origin PolicyとCross Origin Resource Sharingについて調べてみることをおすすめします。

Google Chromeの開発者コンソールやcurl, postmanなどを使ってFuctionsからのレスポンスヘッダを確認すると良いかもしれません。

明確な解答になっていませんが、参考になれば幸いです。

1Like

Comments

  1. @hinokichi77

    Questioner

    ありがとうございます!
    Fetchを使用した書き方のヘッダーを公式ドキュメントを参照して
    https://firebase.google.com/docs/reference/functions/providers_https_?hl=ja#functions_1
    ヘッダーの戻り値をPromiseにしたり、contextから認証情報を使ってみたりしましたが、治らなかったので、XMLHttpRequestを使って書いてみます。

    そもそもCORSを理解していなかったので調べ方を教えていただきとても助かりました!!ありがとうございます!


    exports.sendMail = functions.https.onCall(async(data, context) => {
    // メール設定userMail
    let userMail = {
    from: gmailEmail,//hinokichi
    to: context.auth().email,//userEmail
    subject: `${data.title}の締切1日前です`,//todoTitle
    text: noticeMail(data)
    };
    try {
    await mailTransport.sendMail(userMail);
    } catch (e) {
    console.error(`send failed. ${e}`);
    throw new functions.https.HttpsError('internal', 'send failed');
    }
    });

    (試した表記)

Your answer might help someone💌