回答編集履歴

5

typo fix

2020/07/02 22:43

投稿

YufanLou
YufanLou

スコア463

test CHANGED
@@ -156,7 +156,7 @@
156
156
 
157
157
  content = f.read()
158
158
 
159
- attachment = MIMEText(content, 'comma-separated-values',', 'Shift-JIS')
159
+ attachment = MIMEText(content, 'comma-separated-values', 'Shift-JIS')
160
160
 
161
161
  filename_rfc2047 = Header(filename, 'iso-2022-jp', maxlinelen=55).encode().replace('\n', '')
162
162
 

4

Outlookの特徴に合わせて訂正

2020/07/02 22:43

投稿

YufanLou
YufanLou

スコア463

test CHANGED
@@ -131,3 +131,39 @@
131
131
 
132
132
 
133
133
  `SMTP.sendmail`は`\n`を`\r\n`に変換しますので、上記の必要がありません。
134
+
135
+
136
+
137
+ ## 追記 2
138
+
139
+
140
+
141
+ 少なくともOutlookが RFC 2047 を従ってるはずと思った僕は甘すぎたかもしれません。もっとOutlookのバーションに接近しなきゃいけなさそうです。
142
+
143
+
144
+
145
+ 数えたら、Outlookのencoded wordの一区切りの長さは54、RFC 2047の75と違っています。そして二重引用符の中に行終端がありません。この二つを訂正していきましょう。
146
+
147
+
148
+
149
+ こうしたら残した一致してないところは`;`後の行終端だけなはずですが、どうなりますかね。とりあえず試してみてください。
150
+
151
+
152
+
153
+ ```python
154
+
155
+ with open(filepath, 'rt', encoding='Shift-JIS') as f:
156
+
157
+ content = f.read()
158
+
159
+ attachment = MIMEText(content, 'comma-separated-values',', 'Shift-JIS')
160
+
161
+ filename_rfc2047 = Header(filename, 'iso-2022-jp', maxlinelen=55).encode().replace('\n', '')
162
+
163
+ attachment.set_param('name', filename_rfc2047)
164
+
165
+ attachment.add_header('Content-Disposition', 'attachment', filename=filename_rfc2047)
166
+
167
+ print(attachment)
168
+
169
+ ```

3

linesep について訂正

2020/07/02 22:05

投稿

YufanLou
YufanLou

スコア463

test CHANGED
@@ -122,8 +122,12 @@
122
122
 
123
123
 
124
124
 
125
- `Header`クラスはデフォルトで`\n`を使って行を区切りますが、それはRFCにあっていません。`linesep='\r\n'`をしてみましょう。上記のコードも訂正します。
125
+ ~~`Header`クラスはデフォルトで`\n`を使って行を区切りますが、それはRFCにあっていません。`linesep='\r\n'`をしてみましょう。上記のコードも訂正します。~~
126
126
 
127
127
 
128
128
 
129
- `MIMEText`を構築するときも、`policy`という引数のデフォルトは`compat32`であり、行終端を`\r\n`で指定しています。`policy`を`email.policy.SMTP`にしてみましょう。
129
+ ~~`MIMEText`を構築するときも、`policy`という引数のデフォルトは`compat32`であり、行終端を`\r\n`で指定しています。`policy`を`email.policy.SMTP`にしてみましょう。~~
130
+
131
+
132
+
133
+ `SMTP.sendmail`は`\n`を`\r\n`に変換しますので、上記の必要がありません。

2

linesep について追加

2020/07/02 06:24

投稿

YufanLou
YufanLou

スコア463

test CHANGED
@@ -38,7 +38,7 @@
38
38
 
39
39
  from email.header import Header
40
40
 
41
- contentType = Header('text/comma-separated-values;', header_name='Content-Type')
41
+ contentType = Header('text/comma-separated-values;', header_name='Content-Type', linesep='\r\n')
42
42
 
43
43
  contentType.append('name="')
44
44
 
@@ -48,7 +48,7 @@
48
48
 
49
49
  attachment['Content-Type'] = contentType
50
50
 
51
- contentDisp = Header('attachment;', header_name='Content-Disposition')
51
+ contentDisp = Header('attachment;', header_name='Content-Disposition', linesep='\r\n')
52
52
 
53
53
  contentDisp.append('filename="')
54
54
 
@@ -84,13 +84,17 @@
84
84
 
85
85
  ```python
86
86
 
87
+ from email import policy
88
+
89
+
90
+
87
91
  with open(filepath, 'rt', encoding='Shift-JIS') as f:
88
92
 
89
93
  content = f.read()
90
94
 
91
- attachment = MIMEText(content, 'plain', 'Shift-JIS')
95
+ attachment = MIMEText(content, 'plain', 'Shift-JIS', policy=policy.SMTP)
92
96
 
93
- contentType = Header('text/comma-separated-values;', header_name='Content-Type')
97
+ contentType = Header('text/comma-separated-values;', header_name='Content-Type', linesep='\r\n')
94
98
 
95
99
  contentType.append('name="')
96
100
 
@@ -100,7 +104,7 @@
100
104
 
101
105
  attachment['Content-Type'] = contentType
102
106
 
103
- contentDisp = Header('attachment;', header_name='Content-Disposition')
107
+ contentDisp = Header('attachment;', header_name='Content-Disposition', linesep='\r\n')
104
108
 
105
109
  contentDisp.append('filename="')
106
110
 
@@ -111,3 +115,15 @@
111
115
  attachment['Content-Disposition'] = contentDisp
112
116
 
113
117
  ```
118
+
119
+
120
+
121
+ ## 追記 1
122
+
123
+
124
+
125
+ `Header`クラスはデフォルトで`\n`を使って行を区切りますが、それはRFCにあっていません。`linesep='\r\n'`をしてみましょう。上記のコードも訂正します。
126
+
127
+
128
+
129
+ `MIMEText`を構築するときも、`policy`という引数のデフォルトは`compat32`であり、行終端を`\r\n`で指定しています。`policy`を`email.policy.SMTP`にしてみましょう。

1

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

2020/07/02 06:16

投稿

YufanLou
YufanLou

スコア463

test CHANGED
@@ -66,10 +66,48 @@
66
66
 
67
67
 
68
68
 
69
-
70
-
71
69
  参考:
72
70
 
73
71
  [c# - japanese email subject encoding - Stack Overflow](https://stackoverflow.com/a/492543)
74
72
 
75
73
  [The mess that is attachment filenames – Nodemailer. Blog](https://blog.nodemailer.com/2017/01/27/the-mess-that-is-attachment-filenames/)
74
+
75
+
76
+
77
+ ## 追記
78
+
79
+
80
+
81
+ 問題文と合わせたら、`with open`のブロックはこうなります:
82
+
83
+
84
+
85
+ ```python
86
+
87
+ with open(filepath, 'rt', encoding='Shift-JIS') as f:
88
+
89
+ content = f.read()
90
+
91
+ attachment = MIMEText(content, 'plain', 'Shift-JIS')
92
+
93
+ contentType = Header('text/comma-separated-values;', header_name='Content-Type')
94
+
95
+ contentType.append('name="')
96
+
97
+ contentType.append(filename, charset='iso-2022-jp')
98
+
99
+ contentType.append('"')
100
+
101
+ attachment['Content-Type'] = contentType
102
+
103
+ contentDisp = Header('attachment;', header_name='Content-Disposition')
104
+
105
+ contentDisp.append('filename="')
106
+
107
+ contentDisp.append(filename, charset='iso-2022-jp')
108
+
109
+ contentDisp.append('"')
110
+
111
+ attachment['Content-Disposition'] = contentDisp
112
+
113
+ ```