javascript - Google Apps Script: MailApp.sendEmail() は TEXT ファイルと HTML ファイル以外は送信できません。

okwaves2024-01-25  8

Google Apps Script で MailApp.sendEmail() を使用して送信するメールにファイルを添付しようとしています。ブラウザの JavaScript では、HTML フォームの送信ボタンに相当するものをすでに処理しているため、このコードを使用してファイルを手動で読み取り、動作します。

  var file = document.getElementById('myfile');
  var fileInfo = [];
  if(file.files.length)        // if there is at least 1 file
  {
    if (file.files[0].size < maxEmailAttachmentSize)  // and its size is < 25M
    {
      var reader = new FileReader();
      reader.onload = function(e)
      {
        fileInfo[0] = e.target.result;
      };
      reader.readAsBinaryString(file.files[0]);
      fileInfo[1] = file.files[0].name;
      fileInfo[2] = file.files[0].type;
      fileInfo[3] = file.files[0].size;
    }
    console.log(fileInfo);   // here I see the full file and info. All looks correct.
  }

次に、それをサーバーに送信します。

  google.script.run.withSuccessHandler(emailSent).sendAnEmail(fileInfo);

サーバー上でフィールドを抽出し、次のようにメールを送信します。

  var fname    = fileInfo[1];
  var mimeType = fileInfo[2];
  var fblob    = Utilities.newBlob(fileInfo[0], mimeType, fname);
  // all looks right in the Logger at this point

  try {
    GmailApp.sendEmail(emaiRecipient, emailSubject, emailBody, 
      {
        name: 'Email Sender',  // email sender
        attachments: [fblob]
      }
    );
  catch …

これは、ファイルがテキスト ファイルまたは HTML ファイルの場合は正常に機能しますが、それ以外の場合は機能しません。ファイルは送信されましたが、空であり、明らかに破損しています。このコードのどこが間違っているのかわかる人はいますか? (MailApp.sendEmail() でも機能しません。) 別の stackoverflow の投稿でドキュメントを一度保存​​する必要があることを見ましたが、それは私が必ず行うことですやりたくない。他に方法はありませんか?私に何が欠けているのでしょうか?

1

さらに詳細を追加してください。どのような種類のファイルを添付しようとしていますか?ファイルサイズはどれくらいですか?ファイルには有害、不審、スパムの可能性のあるコンテンツが含まれていますか? FileReader は非同期です。クライアント側のコードはこれをどのように処理していますか?また、再現可能な最小限の例を追加してください。

– ウィケット

2020 年 9 月 4 日 18:08

1

.txt、.HTML、.JPG、.PNG、.PDF を送信してみました。最初の 2 つだけが機能します。これらはすべて比較的小さく、コンソール出力では、ブラウザ側で読み込まれたファイルがサーバーに送信される前に完了していることがわかります。サーバー側では、ファイル内容のログがクライアントのログと同じであることがわかります。たとえば、JPG ファイルや PNG ファイルはサイズが小さいため、明らかに不審なファイルやスパムファイルではありません。サーバー側の MIME タイプは各ファイルに対して正しいです。コードにバグがあるはずですが、何でしょうか?

– ジェフ

2020 年 9 月 4 日 19:29

2

これであなたの質問は解決しましたか? stackoverflow.com/questions/7431365

– ザマスター

2020 年 9 月 4 日 21:11

@TheMaster とても役に立ちます。ありがとう。他はすべて同じにして readAsBinaryString() を readAsArrayBuffer() に変更しようとしましたが、Uncaught T のサーバーで例外が発生しましたypeError: プロパティの値が不正であるため失敗しました: 10。 readAsArrayBuffer() を使用するために、既存のクライアント コードに直接変更を加えることはできますか? V8 ではなく Rhino JavaScript エンジンで実行しているため、Tanaike の優れた例は使用できません。サポートや最新の JavaScript 構文はありません。クソ!

– ジェフ

2020 年 9 月 5 日 17:06

1

@jeff v8 にアップデートします。いずれにせよ、Tanaike のソリューションは完全にクライアント側です。 v8は必要ありません。問題が発生している場合は、別の原因が原因であるため、別途調査する必要があります。

– ザマスター

2020 年 9 月 5 日 18:52



------------------------

修正点: FileReader は非同期プロセスで動作します。これについては、ルーベンのコメントですでに言及されています。 現段階ではバイナリデータをGoogle Apps Script側に送る際に文字列とバイト配列に変換する必要があるようです。これについては、TheMaster のコメントですでに言及されています。 Google Apps Script を使用するには、この場合、次のようにします。ファイルの内容を int8Array のバイト配列に変換することが適切である可能性があることがわかりました。 このために、readAsBinaryString の代わりに readAsArrayBuffer を使用しました。

上記の点をスクリプトに反映すると以下のようになります。

変更されたスクリプト: HTML と Javascript 側:
// Added
function getFile(file) {
  return new Promise((resolve, reject) => {
    var reader = new FileReader();
    reader.onload = (e) => resolve([...new Int8Array(e.target.result)]);
    reader.onerror = (err) => reject(err);
    reader.readAsArrayBuffer(file);
  });
}

async function main() {  // <--- Modified
  var file = document.getElementById('myfile');
  var fileInfo = [];
  if(file.files.length) {
    if (file.files[0].size < maxEmailAttachmentSize) {
      fileInfo[0] = await getFile(file.files[0]);  // <--- Modified
      fileInfo[1] = file.files[0].name;
      fileInfo[2] = file.files[0].type;
      fileInfo[3] = file.files[0].size;
    }
    console.log(fileInfo);   // here I see the full file and info. All looks correct.
    google.script.run.withSuccessHandler(emailSent).sendAnEmail(fileInfo);
  }
}
質問からスクリプト全体についてはわかりませんが、変更されたスクリプトでは main() が実行されると想定されています。 main() が実行されると、ファイルはバイト配列に変換され、fileInfo[0] に配置されます。 Google Apps Script 側では、fileInfo から var fblob = Utilities.newBlob(fileInfo[0], mimeType, fname); Google Apps Script 用の正しい BLOB があります。 Google Apps Script側:

この変更では、Google Apps Script は変更されません。

参考文献: ファイルリーダー FileReader.readAsArrayBuffer() 追加した:

このコードは良さそうですが、V8 ではなく Rhino JavaScript エンジンで実行しているため、使用できません。新しい JavaScript 構文はサポートされていません。古い構文でどのように実行されるかの例を教えていただけますか?参照

上記のコメントを次のように修正しました。

変更されたスクリプト: HTML と Javascript 側:
function main() {
  var file = document.getElementById('myfile');
  var fileInfo = [];
  if(file.files.length) {
    if (file.files[0].size < maxEmailAttachmentSize) {
      var reader = new FileReader();
      reader.onload = function(e) {
        var bytes = new Int8Array(e.target.result);
        var ar = [];
        for (var i = 0; i < bytes.length; i++) {
          ar.push(bytes[i]);
        }
        fileInfo[0] = ar;
        fileInfo[1] = file.files[0].name;
        fileInfo[2] = file.files[0].type;
        fileInfo[3] = file.files[0].size;
        console.log(fileInfo);   // here I see the full file and info. All looks correct.
        google.script.run.withSuccessHandler(emailSent).sendAnEmail(fileInfo);
      }
      reader.onerror = function(err) {
        reject(err);
      }
      reader.readAsArrayBuffer(file.files[0]);
    }
  }
}
Google Apps Script側:

この変更では、Google Apps Script は変更されません。

3

このコードは良さそうですが、Rhino JavaSc で実行しているため使用できません。V8ではなくリップドエンジン。新しい JavaScript 構文はサポートされていません。古い構文でどのように実行されるかの例を教えてください。

– ジェフ

2020 年 9 月 5 日 17:09

1

@jeff 返信ありがとうございます。ご迷惑をおかけし申し訳ございません。あなたの質問から、あなたのブラウザは V8 ランタイムを使用できないことに気づきませんでした。このことについて深くお詫び申し上げます。回答を更新しました。確認していただけますか?ただし、スクリプト編集時に V8 ランタイムを使用していない場合は、Google Apps Script の場合、上記の変更は現在の問題に影響しない可能性があります。 HTMLとJavaScriptはサーバー側で実行されないためです。その際、現在の状況を正しく理解するために、問題を再現するためのスクリプト全体を提供していただけますか?確認させていただきたいのですが。

– 棚池

2020 年 9 月 5 日 23:31

TheMaster Mateo Randwolf それはうまくいきます! Tanaike の 2 番目の例は完璧に機能します。どうもありがとう。そして皆さん、ありがとう!サーバー ランタイムを V8 に切り替えましたが、役に立ちませんでした。しかし、TheMaster の言う通り、そうすべきです。それを使っていること。 (実際にはそうしていましたが、数か月前に Google が行ったマイナーなバグ修正により問題が解決し、Rhino に戻さなければなりませんでした。現在はすべて問題ありません。) MailApp と Gmail アプリに関しては、状況が悪化したため、MailApp から切り替えただけです。働いてない。切り替えて戻ります。ありがとう、ありがとう、特に棚池さん!

– ジェフ

2020 年 9 月 7 日 15:13

総合生活情報サイト - OKWAVES
総合生活情報サイト - OKWAVES
生活総合情報サイトokwaves(オールアバウト)。その道のプロ(専門家)が、日常生活をより豊かに快適にするノウハウから業界の最新動向、読み物コラムまで、多彩なコンテンツを発信。