0

My problem is that while sending email in django i want to attach a file.

If i do it that way:

email.attach("Random_name", uploaded_file.read()) 

it works and my email sends. But if instead of string "Random name" i put a variable there representing uploaded file name as:

        uploaded_file = request.FILES['stl_file']
        uploaded_file_name = request.FILES['stl_file'].name
        email.attach(uploaded_file_name, uploaded_file.read())

the whole things blows up and i get a ValueError "need more than 1 value to unpack" for email.send() method. I have checked both variables upload_file and upload_file_name(by use of pdb tool) and both of them get the right value before calling attach method.
Here is my view where i am trying to send the mail:

    def print(request):

   if request.method == 'POST':
        form = PrintForm(data=request.POST, request = request)

        if form.is_valid():
            contact_name = request.POST.get('contact_name', '')
            contact_email = request.POST.get('contact_email', '')
            form_content = request.POST.get('content', '')
            supervisor = form.cleaned_data['supervisor']
            template = get_template('threeD/email/contact_template_for_printing.txt')
            context = Context({
                'contact_name': contact_name,
                'supervisor': supervisor,
                'contact_email': contact_email,
                'form_content': form_content,
            })
            content = template.render(context)
            subject = "New message"

            email = EmailMessage(
                    subject,
                    content,
                    contact_email,
                    [supervisor],
                    headers={'Reply-To': contact_email}
            )
            if request.FILES:
                uploaded_file = request.FILES['stl_file']
                uploaded_file_name = request.FILES['stl_file'].name
                email.attach(uploaded_file_name, uploaded_file.read())
            email.send()

            messages.success(request, "Thank you for your message.")
            return redirect('/index/print/')

   else:
            form = PrintForm(request=request)
   context_dict = {}
   context_dict['printers'] = Printer.objects.all()
   context_dict['form'] = form
   return render(request, 'threeD/print.html', context_dict)

and my form:

class PrintForm(forms.Form):
    contact_name = forms.CharField(required=True)
    contact_email = forms.EmailField(required=True)
    supervisor = forms.ChoiceField(
        choices=[(str(sup.email), str(sup.name)) for sup in Supervisors.objects.all()]
    )
    stl_file = forms.FileField(required=False)
    stl_file.help_text = "Upload your file as .STL format. If you have more than one file, " \
                     "make a .zip and upload them all at once"
    content = forms.CharField(
        required=True,
        widget=forms.Textarea
    )

So the error i am getting is like that: http://dpaste.com/2YZQ941
I would be very much grateful for any help.
I m using Django 1.9 version

SOLVED
Finally solves by hard-codding file type to be 'application/octet-stream', such as:

        uploaded_file = request.FILES['stl_file']
        uploaded_file_name = request.FILES['stl_file'].name
        email.attach(uploaded_file_name, uploaded_file.read(), 'application/octet-stream')
        email.send()
Ilja Leiko
  • 426
  • 2
  • 7
  • 22

1 Answers1

1

I think it needs a content type, maybe try something more like this

uploaded_file = form.cleaned_data.get('stl_file', '')
email.attach(uploaded_file.name, uploaded_file.read(), uploaded_file.content_type)
davidejones
  • 1,869
  • 1
  • 16
  • 18
  • Thank you, davidejones, for your comment. Well, i have tried - it doesn't work. If i change upload_file = form.cleaned_data.get(...) then i get "'NoneType' object has no attribute 'read'" on the line when i attach file – Ilja Leiko Apr 18 '17 at 15:58
  • oh ok sounds like you might not have stl_file in your django form then. If request FILES works you should try the same code but with `uploaded_file = request.FILES['stl_file']` and see if that works. I think the main thing is making sure to pass a content type – davidejones Apr 18 '17 at 16:00
  • Django documentation says that content type is an optional stuff. But i have tried putting it in as: email.attach(uploaded_file_name, uploaded_file.read(), uploaded_file_type), where uploaded_file_type = request.FILES['stl_file'].content_type (i checked with pdb the variable gets value), but it's still the same annoying ValueError – Ilja Leiko Apr 18 '17 at 16:04
  • Well according to that error at dpaste it is having trouble parsing the mime type which is the last parameter in `email.attach()` to me its almost like its a blank string. Can you tell me the `uploaded_file_name` and `uploaded_file_type` variable values are? – davidejones Apr 18 '17 at 16:58
  • 2
    'simplify3d_stl' doesn't seem right try hardcode the type like this `email.attach(uploaded_file_name, uploaded_file.read(), 'application/octet-stream')` – davidejones Apr 18 '17 at 17:54
  • woooow, dang it.... IT WORKS now! Finally!!! Mate, you are a magician :O Thank you SOOO much! – Ilja Leiko Apr 18 '17 at 18:13
  • Awesome! can you accept an answer on both your questions – davidejones Apr 18 '17 at 18:15