基本はこちらのJavaで書かれた方法と同じことがしたいわけだが、Gmail API ではメール本文がBase64という形式にエンコードされて返ってくる。これががURL-Safeな形式になっている関係でデコードに苦戦したのでメモ。
Gmail API での Get の方法
公式リファレンスは下記。https://developers.google.com/gmail/api/v1/reference/users/messages/get
実際にTry it now
でどういう値が返ってくるのかを試すことができる。
このヘッダーパラメーター?として付与できるformat
がデフォルトではfull
なのだが、raw
の場合に取得できるメール本文(正確にはraw
の中にある本文に該当する部分)と違い、URL-Safeな形式に変換されたBase64の文字列が返ってくる。
具体的には「+」→「-」、「/」→「_」、「=」→削除という風に変換された形式でしか取得できない。これを最終的にUTF-8の文字列にしたいので、いろんなメソッドを使って変換するのに苦労した。
デコードの流れ
- Gmailから返ってくるのはString型のエンコードされた本文
- 一度URL-UnsafeなBase64のData型にする
- それをStringに戻す(これで
format: raw
の場合と同じ文字列が取得できる) - 再度Data型にする
- UTF-8でStringにする
func decodeParts(_ parts: [[String: Any]]) -> [String: String]? {
var decodedParts: [String: String] = [:]
for part in parts {
guard let partId = part["partId"] as? String,
let body = part["body"] as? [String: Any],
let bodydata = body["data"] as? String else {
return nil
}
guard let urlUnsafebase64Data = GTLRDecodeWebSafeBase64(bodydata) else {
return nil
}
let base64EncodedString = urlUnsafebase64Data.base64EncodedString(options: .lineLength64Characters)
guard let base64Data = Data(base64Encoded: base64EncodedString, options: .ignoreUnknownCharacters) else {
return nil
}
guard let utf8DecodedString = String(data: base64Data, encoding: .utf8) else {
return nil
}
decodedParts["\(partId)"] = utf8DecodedString
}
return decodedParts
}
Swiftは久々に書くのでコードがキレイでなかったり無駄が多いと思う。神な方からのコメントや編集リクエスト待ってます。
Base64→UTF-8の変換は以下のWebサービスが使いやすいです。
https://www.base64decode.org/
もしこの記事が役に立ったら、いいねしてくれると喜びます。