61805


django.core.mail.EmailMessageを、利用して、WEBアプリ内に問い合わせフォームの実装を行っております。

ローカルの環境で開発しており、受信するメールの内容は、コンソールに表示させています。

その際に、フォーム内のタイトルの項目で入力した内容を、メールのタイトルで受信するように設定していますが、タイトルが文字化けしてしまいます。

メール本文は、文字化けせずに表示されます。  
また、コンソールの１行目に【Content-Type: text/plain;
charset="utf-8"】と表示があるのでUTF-8の設定になっているとみていますが、どうして文字化けするかわかりません。

解決の方法について、ご教授いただきないでしょうか？  
実行環境と関係ファイルのコードは以下の内容です。

実行環境  
Mac: mojave 10.14.6  
Python: 3.7.5  
Django: 3.0.0

メール受信内容のコンソール内容(４行目が文字化け箇所）

[code]

    Content-Type: text/plain; charset="utf-8"
    MIME-Version: 1.0
    Content-Transfer-Encoding: 8bit
    Subject: =?utf-8?b?44GK5ZWP44GE5ZCI44KP44GbIHt9?=
    From: admin@example.com
    To: test@example.com
    Cc: sample@example.com
    Date: Thu, 26 Dec 2019 04:24:29 -0000
    Message-ID: <157733426951.17628.14334668042684224451@ApplenoMacBook-Pro.local>
    
    送信者名: テストユーザー
    メールアドレス: sample@example.com
    メッセージ:
    テスト
    -------------------------------------------------------------------------------
    
[/code]

forms.py

[code]

    from django import forms
    from django.core.mail import EmailMessage
    
    
    class InquiryForm(forms.Form):
        name = forms.CharField(label='お名前', max_length=30)
        email = forms.EmailField(label='メールアドレス')
        title = forms.CharField(label='タイトル', max_length=30)
        message = forms.CharField(label='メッセージ', widget=forms.Textarea)
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
            self.fields['name'].widget.attrs['class'] = 'form-control col-9'
            self.fields['name'].widget.attrs['placeholder'] = 'お名前をここに入力してください。'
    
            self.fields['email'].widget.attrs['class'] = 'form-control col-11'
            self.fields['email'].widget.attrs['placeholder'] = 'メールアドレスをここに入力してください。'
    
            self.fields['title'].widget.attrs['class'] = 'form-control col-11'
            self.fields['title'].widget.attrs['placeholder'] = 'タイトルをここに入力してください。'
    
            self.fields['message'].widget.attrs['class'] = 'form-control col-12'
            self.fields['message'].widget.attrs['placeholder'] = 'メッセージをここに入力してください。'
    
        def send_email(self):
            name = self.cleaned_data['name']
            email = self.cleaned_data['email']
            title = self.cleaned_data['title']
            message = self.cleaned_data['message']
    
            subject = 'お問い合わせ {}'.format(title)
    
            message = '送信者名: {0}\nメールアドレス: {1}\nメッセージ:\n{2}'.format(name, email, message)
            from_email = 'admin@example.com'
            to_list = [
                'test@example.com'
            ]
            cc_list = [
                email
            ]
    
            message = EmailMessage(subject=subject, body=message, from_email=from_email, to=to_list, cc=cc_list)
            message.send()
    
[/code]

views.py

[code]

    import logging
    
    from django.urls import reverse_lazy
    from django.views import generic
    from .forms import InquiryForm
    
    logger = logging.getLogger(__name__)
    
    class InquiryView(generic.FormView):
        template_name = 'inquiry.html'
        form_class = InquiryForm
        success_url = reverse_lazy('main:welcome')
    
        def form_valid(self, form):
            form.send_email()
            logger.info('Inquiry sent by {}'.format(form.cleaned_data['name']))
            return super().form_valid(form)
    
[/code]

inquiry.html

[code]

    {% extends 'layout.html' %}
    
    {% block title %}お問い合わせ{% endblock %}
    
    {% block active_inquiry %}active{% endblock %}
    
    {% block body %}
    <body class="login">
    <div>
        <a class="hiddenanchor" id="signup"></a>
        <a class="hiddenanchor" id="signin"></a>
        <div class="login_wrapper">
            <div class="animate form login_form">
                <section class="login_content">
                    <form method="post">
                        {% csrf_token %}
    
                        {{ form.non_field_errors }}
    
                        {% for field in form %}
                        <div class="form-group row">
                            <label for="{{ field.id_for_label }}" class="col-sm-4 col-form-label">
                                <strong>{{ field.label_tag }}</strong>
                            </label>
                            <div class="col-sm-8">
                                {{ field }}
                                {{ field.errors }}
                            </div>
                        </div>
                        {% endfor %}
    
                        <div class="offset-sm-4 col-sm-8">
                            <button class="btn btn-primary" type="submit">送信</button>
                        </div>
                    </form>
                </section>
            </div>
        </div>
    </div>
    {% endblock %}
    
[/code]

settings.py

[code]

    EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
    
[/code]


CC BY-SA 4.0
2019-12-26T05:01:04.783
61798
2019-12-26T08:06:32.893
36988
question
python3 django
django.core.mail.EmailMessageクラスでメールを送信すると、タイトルが文字化けする対策を教えてください


自己回答となりますが、下記のサイトに関係する内容がありましたので、今回の質問の対応について紹介させてもらいます。  
参考サイト）<https://speakerdeck.com/thinkami/djangocongress-jp-2019-talk>

[code]

    EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
    
[/code]

の設定で、コンソールにメールの内容を表示する場合は、件名が日本語にならないのが、デフォルトの設定のようです。

私の場合も、最初の質問で載せた、ファイルとコードのまま、本番環境へデプロイを行い、問い合わせフォームより、メールを送信すると日本語で表示されました。

それでも、ローカルの環境で件名を日本語で見たい場合は、console.EmailBackendを拡張(write_message()
メソッドをオーバーライド)する必要がありました。

myapp.email_backends.py

[code]

    class ReadableSubjectEmailBackend(console.EmailBackend):
    def write_message(self, message):
    from email.header import decode_header
    subject = message.message().get('Subject')
    decoded_tuple = decode_header(subject)
    # => [('Django', None)] # MIMEヘッダエンコーディングなし
    # => [(b'\xe3\x82\xb8\xe3\x83\xa3\xe3\x83\xb3\xe3\x82\xb4', 'utf-8')]
    if decoded_tuple[0][1] is not None:
    readable_subject = decoded_tuple[0][0].decode(
    decoded_tuple[0][1])
    self.stream.write(f'\nSubject (日本語表示): {readable_subject}\n')
    super().write_message(message
    
[/code]

settengs.py

[code]

    EMAIL_BACKEND = 'myapp.email_backends.ReadableSubjectEmailBackend'
    
[/code]

コンソール表示

[code]

    Subject (日本語表示): ジャンゴ
    Content-Type: text/plain; charset="utf-8"
    Subject: =?utf-8?b?44K444Oj44Oz44K0?=
    
[/code]


CC BY-SA 4.0
2019-12-26T08:06:32.893
61805
2019-12-26T08:06:32.893
36988
61798
answer