🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

4050閲覧

django メール送信時ができない。BadHeaderError

atk_721

総合スコア62

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2019/10/18 18:15

編集2019/10/18 18:17

前提・実現したいこと

BadHeaderErrorはなんなのか理解したい、メールを送信できるようにしたい。

会員登録機能を実装しているのですが、BadHeaderErrorというものが
発生して困っています。
ヘッダー値に改行を含めることができないという意味だと思うのですが、
ヘッダー値が何をさしているのかはっきりとわかりません。

発生している問題・エラーメッセージ

BadHeaderError Exception Value: Header values can't contain newlines (got '会員登録を受け付けました\n' for header 'Subject')

views.py

from django.shortcuts import render from django.views import generic from .models import * from django.contrib.auth.views import LoginView from .forms import LoginForm,SignUPForm from django.contrib.sites.shortcuts import get_current_site from django.core.signing import dumps,SignatureExpired,BadSignature,loads from django.template.loader import get_template from django.contrib import messages from django.http import HttpResponseRedirect,HttpResponseBadRequest from django.urls import reverse from django.conf import settings # Create your views here. class Lp(generic.TemplateView): template_name = 'ec/lp.html' def get_context_data(self,**kwargs): context = super().get_context_data() context = { 'items':Product.objects.all(), } return context class ItemList(generic.ListView): model = Product template_name = 'ec/item_list.html' def get_queryset(self): queryset = Product.objects.all() if "keyword" in self.request.GET and self.request.GET['keyword'] != None: keyword = self.request.GET['keyword'] queryset = Product.objects.filter(name__icontains=keyword) return queryset class ItemDetail(generic.DetailView): model = Product template_name = 'ec/item_detail.html' class Login(LoginView): form_class = LoginForm template_name = 'ec/login.html' class SignUp(generic.CreateView): template_name = 'ec/signup.html' model = User form_class = SignUPForm def form_valid(self,form): user = form.save(commit=False) user.is_active = False user.save() current_site = get_current_site(self.request) domain = current_site.domain context = { 'protocol':self.request.scheme, 'domain':domain, 'token':dumps(user.pk), 'user':user, } subject_template = get_template('ec/mail_template/signup/subject.txt') subject = subject_template.render(context) message_template = get_template('ec/mail_template/signup/message.txt') message = message_template.render(context) user.email_user(subject,message)#TrackBack、ここで止まっている。 messages.success(self.request,'仮登録完了です') return HttpResponseRedirect(reverse('ec:signup')) class SignUpDone(generic.TemplateView): template_name = 'ec/signup_done.html' timeout_seconds = getattr(settings,'ACTIVATION_TIMEOUT_SECONDS',60*60*24) def get(self,request,**kwargs): token = kwargs.get('token') try: user_pk = loads(token,max_age=timeout_seconds) except SignatureExpired: return HttpResponseBadRequest() except BadSignature: return HttpResponseBadRequest() else: try: user = User.objects.get(pk=user.pk) except User.DoesNotExist: return HttpResponseBadRequest() else: if not user.is_active: user.active = True user.save() return super().get(request,**kwargs) return HttpResponseBadRequest()

models.py

from django.db import models from django.contrib.auth.base_user import BaseUserManager,AbstractBaseUser from django.contrib.auth.models import PermissionsMixin from django.core.mail import send_mail from django.utils.translation import ugettext_lazy as _ from django.utils import timezone # Create your models here. class Product(models.Model): class Meta: db_table = 'product' verbose_name ='商品' verbose_name_plural = '商品' thumbnail = models.ImageField(verbose_name='商品画像',upload_to='thumbnails/') name = models.CharField(verbose_name='名前',max_length=255,blank=False,null=False) price = models.IntegerField(verbose_name='価格') description = models.TextField(verbose_name='商品説明') class MyUserManager(BaseUserManager): use_in_migrations = True def _create_user(self,email,password,**extra_fields): if not email: raise ValueError('The given imail must be set') user = self.model(email=email, **extra_fields) user.set_password(password) user.save(using=self._db) return user def create_user(self,email,password=None,**extra_fields): extra_fields.setdefault('is_staff',False) extra_fields.setdefault('is_superuser',False) return self._create_user(email,password,**extra_fields) def create_superuser(self,email,password,**extra_fields): extra_fields.setdefault('is_staff',True) extra_fields.setdefault('is_superuser',True) if extra_fields.get('is_staff') is not True: raise ValueError('superuser must have is_staff=True.') if extra_fields.get('is_superuser') is not True: raise ValueError('superuser must have is_superuser=True.') return self._create_user(email,password,**extra_fields) class User(AbstractBaseUser, PermissionsMixin): class Meta: verbose_name = 'ユーザー' verbose_name_plural = 'ユーザー' email = models.EmailField('メールアドレス',max_length=150,null=False,blank=False,unique=True) name = models.CharField('名前',max_length=150,null=False,blank=False) is_staff = models.BooleanField( '管理者', default = False, help_text=_( 'Designates whether the user can log into this admin site.'), ) is_active = models.BooleanField( '有効', default=True, help_text=_( 'Designates whether this user should be treated as active. ' 'Unselect this instead of deleting accounts.' ), ) date_joined = models.DateTimeField(_('date joined'),default=timezone.now) objects = MyUserManager() EMAIL_FIELD = 'email' USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['name'] def email_user(self,subject,message,from_email=None,**kwargs): #"""Send an email to this user.""" send_mail(subject,message,from_email,[self.email],**kwargs) @property def username(self): return self.email

forms.py

from django import forms from django.contrib.auth import get_user_model from django.contrib.auth.forms import AuthenticationForm,UserCreationForm from .models import * from django.core.exceptions import ValidationError class LoginForm(AuthenticationForm): def __init__(self,*args,**kwargs): super().__init__(*args,**kwargs) for field in self.fields.values(): field.widget.attrs['class'] = 'form-control' field.widget.attrs['placeholder'] = field.label class SignUPForm(UserCreationForm): class Meta: model = User fields = ('email','name') def __init__(self,*args,**kwargs): super().__init__(*args,**kwargs) for field in self.fields.values(): field.widget.attrs['class'] = 'form-control' field.widget.attrs['placeholder'] = field.label

subject.txt

会員登録を受け付けました

message.txt

{{ user.name }} 様 会員登録手続きを実施いただき、ありがとうございます。 下記URLよりサイトにアクセスの上、本登録をお願いいたします。 まだ会員登録手続きは完了しておりませんのでご注意ください。 本登録用URL {{protocol}}://{{domain}}{% url 'ec:signup_done' token %}

settings.py

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

試したこと

会員登録を受け付けました\n'の\nが引っかかいると、思い改行を消したのですが消えずにTrackBackの最後の処理は

raise BadHeaderError("Header values can't contain newlines (got %r for header %r)" % (val, name)) … ▼ Local vars Variable Value encoding 'utf-8' name 'Subject' val '会員登録を受け付けました\n'

のようになっておりなぜか改行(\n)が消えません。サーバーの再起動は行いました。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。
python3.7.3
django2.2

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

views.py

def form_valid(self,form): # ... subject_template = get_template('ec/mail_template/signup/subject.txt') subject = subject_template.render(context).strip()

strip() を使用して改行を取り除くのが良いかと思いますmm

ドキュメント

投稿2019/10/18 19:32

unhappychoice

総合スコア1531

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

atk_721

2019/10/18 20:03

回答ありがとうございます、解決することができました!これはtxtファイルからの場合自動で改行されるという認識でいいんでしょうか?
unhappychoice

2019/10/18 20:08 編集

というわけではなく、txtの改行削除すればよいのですが > 会員登録を受け付けました\n'の\nが引っかかいると、思い改行を消したのですが消えずにTrackBackの最後の処理は > raise BadHeaderError("Header values can't contain newlines (got %r for header %r)" では `\r` が残っているようでした。お使いのエディタや環境によって異なりますが `\r` までしっかり削除すれば問題なかったと思います。 https://ja.stackoverflow.com/questions/12897/改行の-nと-r-nの違いは何ですか ただ、今回の処理だと txt にうっかり改行が紛れ込ませてエラーになるよりは、コードで取り除くようにしたほうが確実かと思っています。
atk_721

2019/10/18 20:52

なるほど!理解が深まりました。リンク先など貼っていただきありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問