LoginSignup
2
3

More than 5 years have passed since last update.

Gmailの下書きをMarkdownで書くためのアプリをelectron-vueで作る

Posted at

勤務先では日報をメール(Gmail)で出すこととなっているのですが、いちいちメール画面を開いて記録つけてると気が散るしいまいち編集画面が使いやすくない(※個人の感想です)ので、自分は下書きは自動バックアップ機能のあるVisual Studio Codeで書いていたり。

それだと書式が付けられないので、Markdownで清書するアプリを書いてみます。

ソースはこちら。
https://github.com/kuinaein/md-gmail/compare/0b4913e...3d66c13

なお、Node.jsでのGmail APIの呼び出し方は下記の記事にも書いたのでそのあたりは割愛します。

ライブラリのインストール

Markdownライブラリはmarkedを使うことにします。

vue init simulatedgreg/electron-vue md-gmail
cd md-gmail
yarn add --dev pug-html-loader
yarn add googleapis urlsafe-base64 moment marked html-escaper
yarn add bootstrap-honoka

Markdownプレビュー画面

Googleアカウントの認証については別の記事で書いたのでざっくり飛ばします。

Markdownの整形自体はmarkedがやってくれるので画面自体はシンプルなものです。
ただmarkedはテーブルタグに枠線を付けてくれないので、表示画面ではひとまずスタイルシートで補っています。vue-loaderは画面にない要素へのスタイル定義を削ろうとするので、「>>>」で子要素へ影響するものと指示しておきます。

<template lang="pug">
.container
  textarea(v-model="md" rows="15" style="width:90vw")
  p プレビュー:
  div(id="formatted" v-html="formatted")
  button.btn.btn-primary(type="button" @click="saveAsDraft") Gmail下書きに保存
</template>

<style scoped>
#formatted >>> table {
  border-collapse: collapse;
}
#formatted >>> th, #formatted >>> td {
  border: solid 1px black;
}
</style>

<script>
import moment from 'moment'
import URLSafeBase64 from 'urlsafe-base64'
import { google } from 'googleapis'
import marked from 'marked'
import { escape as escapeHtml } from 'html-escaper'

const BOUNDARY = 'MY_BOUNDARY_GX9900'

export default {
  data () {
    return {
      md: ''
    }
  },
  computed: {
    formatted () {
      return marked(this.md)
    }
  },
  // 後略
}
</script>

Gmailの下書きへ保存

markedの出力結果を保存するだけ……なのですがいくつか注意点があります。

  • Gmail APIにはRFC822に沿った生のメールデータをURLセーフなBase64形式にして渡す必要がある。
  • HTMLメールの場合はContent-Type: multipart/alternativeとして送る必要がある。全体をtext/htmlにしてもダメ。
    • ただし、テキスト形式の本文を含める必要はない。
  • HTMLメールにしても<head>タグの内容は無視される。style属性等に書き換える必要がある。

また、本文のMarkdown形式でのソースも残しておきたいので、それも文中に含めることとします。

const body = this.formatted.replace(/<table>/g,
  '<table border="1" style="border-collapse:collapse">') + `
<br/><br/>
<small>Markdownソース:
<textarea readonly rows="1" cols="1">${escapeHtml(this.md)}</textarea></small>
`
const subject = '【日報】' + moment().format('YYMMDD')
const email = `Subject: =?UTF-8?B?${URLSafeBase64.encode(Buffer.from(subject))}?=
Content-Type: multipart/alternative; boundary="${BOUNDARY}"

--${BOUNDARY}
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: base64

${Buffer.from(body).toString('base64')}
--${BOUNDARY}--`
gmail.users.drafts.create({
  userId: 'me',
  resource: { message: { raw: URLSafeBase64.encode(Buffer.from(email)) } }
})
2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3