質問するログイン新規登録

回答編集履歴

5

typo fix

2020/07/02 22:43

投稿

YufanLou
YufanLou

スコア466

answer CHANGED
@@ -77,7 +77,7 @@
77
77
  ```python
78
78
  with open(filepath, 'rt', encoding='Shift-JIS') as f:
79
79
  content = f.read()
80
- attachment = MIMEText(content, 'comma-separated-values',', 'Shift-JIS')
80
+ attachment = MIMEText(content, 'comma-separated-values', 'Shift-JIS')
81
81
  filename_rfc2047 = Header(filename, 'iso-2022-jp', maxlinelen=55).encode().replace('\n', '')
82
82
  attachment.set_param('name', filename_rfc2047)
83
83
  attachment.add_header('Content-Disposition', 'attachment', filename=filename_rfc2047)

4

Outlookの特徴に合わせて訂正

2020/07/02 22:43

投稿

YufanLou
YufanLou

スコア466

answer CHANGED
@@ -64,4 +64,22 @@
64
64
 
65
65
  ~~`MIMEText`を構築するときも、`policy`という引数のデフォルトは`compat32`であり、行終端を`\r\n`で指定しています。`policy`を`email.policy.SMTP`にしてみましょう。~~
66
66
 
67
- `SMTP.sendmail`は`\n`を`\r\n`に変換しますので、上記の必要がありません。
67
+ `SMTP.sendmail`は`\n`を`\r\n`に変換しますので、上記の必要がありません。
68
+
69
+ ## 追記 2
70
+
71
+ 少なくともOutlookが RFC 2047 を従ってるはずと思った僕は甘すぎたかもしれません。もっとOutlookのバーションに接近しなきゃいけなさそうです。
72
+
73
+ 数えたら、Outlookのencoded wordの一区切りの長さは54、RFC 2047の75と違っています。そして二重引用符の中に行終端がありません。この二つを訂正していきましょう。
74
+
75
+ こうしたら残した一致してないところは`;`後の行終端だけなはずですが、どうなりますかね。とりあえず試してみてください。
76
+
77
+ ```python
78
+ with open(filepath, 'rt', encoding='Shift-JIS') as f:
79
+ content = f.read()
80
+ attachment = MIMEText(content, 'comma-separated-values',', 'Shift-JIS')
81
+ filename_rfc2047 = Header(filename, 'iso-2022-jp', maxlinelen=55).encode().replace('\n', '')
82
+ attachment.set_param('name', filename_rfc2047)
83
+ attachment.add_header('Content-Disposition', 'attachment', filename=filename_rfc2047)
84
+ print(attachment)
85
+ ```

3

linesep について訂正

2020/07/02 22:05

投稿

YufanLou
YufanLou

スコア466

answer CHANGED
@@ -60,6 +60,8 @@
60
60
 
61
61
  ## 追記 1
62
62
 
63
- `Header`クラスはデフォルトで`\n`を使って行を区切りますが、それはRFCにあっていません。`linesep='\r\n'`をしてみましょう。上記のコードも訂正します。
63
+ ~~`Header`クラスはデフォルトで`\n`を使って行を区切りますが、それはRFCにあっていません。`linesep='\r\n'`をしてみましょう。上記のコードも訂正します。~~
64
64
 
65
- `MIMEText`を構築するときも、`policy`という引数のデフォルトは`compat32`であり、行終端を`\r\n`で指定しています。`policy`を`email.policy.SMTP`にしてみましょう。
65
+ ~~`MIMEText`を構築するときも、`policy`という引数のデフォルトは`compat32`であり、行終端を`\r\n`で指定しています。`policy`を`email.policy.SMTP`にしてみましょう。~~
66
+
67
+ `SMTP.sendmail`は`\n`を`\r\n`に変換しますので、上記の必要がありません。

2

linesep について追加

2020/07/02 06:24

投稿

YufanLou
YufanLou

スコア466

answer CHANGED
@@ -18,12 +18,12 @@
18
18
 
19
19
  ```python
20
20
  from email.header import Header
21
- contentType = Header('text/comma-separated-values;', header_name='Content-Type')
21
+ contentType = Header('text/comma-separated-values;', header_name='Content-Type', linesep='\r\n')
22
22
  contentType.append('name="')
23
23
  contentType.append(filename, charset='iso-2022-jp')
24
24
  contentType.append('"')
25
25
  attachment['Content-Type'] = contentType
26
- contentDisp = Header('attachment;', header_name='Content-Disposition')
26
+ contentDisp = Header('attachment;', header_name='Content-Disposition', linesep='\r\n')
27
27
  contentDisp.append('filename="')
28
28
  contentDisp.append(filename, charset='iso-2022-jp')
29
29
  contentDisp.append('"')
@@ -41,17 +41,25 @@
41
41
  問題文と合わせたら、`with open`のブロックはこうなります:
42
42
 
43
43
  ```python
44
+ from email import policy
45
+
44
46
  with open(filepath, 'rt', encoding='Shift-JIS') as f:
45
47
  content = f.read()
46
- attachment = MIMEText(content, 'plain', 'Shift-JIS')
48
+ attachment = MIMEText(content, 'plain', 'Shift-JIS', policy=policy.SMTP)
47
- contentType = Header('text/comma-separated-values;', header_name='Content-Type')
49
+ contentType = Header('text/comma-separated-values;', header_name='Content-Type', linesep='\r\n')
48
50
  contentType.append('name="')
49
51
  contentType.append(filename, charset='iso-2022-jp')
50
52
  contentType.append('"')
51
53
  attachment['Content-Type'] = contentType
52
- contentDisp = Header('attachment;', header_name='Content-Disposition')
54
+ contentDisp = Header('attachment;', header_name='Content-Disposition', linesep='\r\n')
53
55
  contentDisp.append('filename="')
54
56
  contentDisp.append(filename, charset='iso-2022-jp')
55
57
  contentDisp.append('"')
56
58
  attachment['Content-Disposition'] = contentDisp
57
- ```
59
+ ```
60
+
61
+ ## 追記 1
62
+
63
+ `Header`クラスはデフォルトで`\n`を使って行を区切りますが、それはRFCにあっていません。`linesep='\r\n'`をしてみましょう。上記のコードも訂正します。
64
+
65
+ `MIMEText`を構築するときも、`policy`という引数のデフォルトは`compat32`であり、行終端を`\r\n`で指定しています。`policy`を`email.policy.SMTP`にしてみましょう。

1

問題文と合わせるコードを追加

2020/07/02 06:16

投稿

YufanLou
YufanLou

スコア466

answer CHANGED
@@ -32,7 +32,26 @@
32
32
 
33
33
  参考と問題を分析しただけの結果ですので、100%の把握がないけど、お役に立てたら幸いです。
34
34
 
35
-
36
35
  参考:
37
36
  [c# - japanese email subject encoding - Stack Overflow](https://stackoverflow.com/a/492543)
38
- [The mess that is attachment filenames – Nodemailer. Blog](https://blog.nodemailer.com/2017/01/27/the-mess-that-is-attachment-filenames/)
37
+ [The mess that is attachment filenames – Nodemailer. Blog](https://blog.nodemailer.com/2017/01/27/the-mess-that-is-attachment-filenames/)
38
+
39
+ ## 追記
40
+
41
+ 問題文と合わせたら、`with open`のブロックはこうなります:
42
+
43
+ ```python
44
+ with open(filepath, 'rt', encoding='Shift-JIS') as f:
45
+ content = f.read()
46
+ attachment = MIMEText(content, 'plain', 'Shift-JIS')
47
+ contentType = Header('text/comma-separated-values;', header_name='Content-Type')
48
+ contentType.append('name="')
49
+ contentType.append(filename, charset='iso-2022-jp')
50
+ contentType.append('"')
51
+ attachment['Content-Type'] = contentType
52
+ contentDisp = Header('attachment;', header_name='Content-Disposition')
53
+ contentDisp.append('filename="')
54
+ contentDisp.append(filename, charset='iso-2022-jp')
55
+ contentDisp.append('"')
56
+ attachment['Content-Disposition'] = contentDisp
57
+ ```