В прикрепленном изображении Nodemailer нет данных

Я пытаюсь отправить вложение с изображением, и оно проходит, но без данных. 0kb размером. Это использует этот код:

var path = require('path');
var uploadDir = path.dirname(require.main.filename); 
// This actually produces a filepath that starts at my /Applications dir on my Mac, but ends in the right spot.

var img = require("fs").readFileSync(uploadDir + '/uploads/' + params.newFileName);
// file was upload was handled on the server by multer and renamed to something like this: fc5c5921bd0892f114cd7b6f0d39d9a3.gif

attachments: [{
    filename: params.newFileName,
    filePath: img
}]

Я перепробовал около сотни вариантов на эту тему, основываясь на своем онлайн-исследовании, и либо я вообще не получаю вложения, либо результат, описанный выше, либо общий файл вложения-1.bin. Мой параметр newFileName в порядке. Файл существует в указанном каталоге. Явных ошибок нет. Я бы очень хотел получить некоторые рекомендации :)

обновить

Вот шаги, ведущие к шаткому прикреплению файла от клиента к серверу.

Метод контроллера:

$scope.Upload = function()
{
    var file = $scope.fileModel;
    var uploadUrl = '/upload';

    if (formValid)
    {
        // Upload it
        fileUpload.uploadFileToUrl(file, uploadUrl);
    }
};

Служба, в которой находится функция загрузки (мне не удалось найти способ отправить файл с остальной частью формы, поэтому загрузка обрабатывается отдельно, и я устанавливаю значение скрытого ввода в multer-renamed имя файла, который отправляется вместе с формой):

uploadFileToUrl: function(file, uploadUrl)
{
    var fd = new FormData();
    fd.append('file', file);
    $http.post(uploadUrl, fd, 
    {
        transformRequest: angular.identity,
        headers: {
            'Content-Type': undefined
        }
    })

    .success(function (res)
    {
        toastr.success(res.successMessage, 'Success');
        $('#file-name').val(res.fileName)
        $('#file-name').trigger('input');
    })

    .error(function()
    {
        toastr.error(res.errorMessage, 'Error');
    });
}

Данные формы обрабатываются на сервере двумя способами, первый из которых сохраняет параметры в сеансе, а затем отправляет пользователя в Paypal для завершения платежа, а второй из которых обращается к этим переменным сеанса, создает и отправляет электронное письмо:

// NOTE: leaving out the paypal code as it is not relevant
CompletePayment: function(req, res)
{
    // Get the request params
    var params = req.body;

    // Store request params in session variables so we can send 
    // confirmation emails once payment has been completed
    req.session.requestFormData = {
        mediaType: params.mediaType,
        name: params.name,
        email: params.email,
        dedication: params.dedication,
        notes: params.notes,
        socialMedia: params.socialMedia,
        newFileName: params.newFileName
    }
}

Наконец, метод, который создает и отправляет сообщение — на самом деле два, основное сообщение и подтверждение пользователю (очевидно, заменяя конфиденциальную информацию заполнителями):

SendRequestEmail: function(req, res)
{
    var params = req.session.requestFormData;
    // I split the nodemailer SMTP transport off into a service
    var transport = EmailService.SetupTransport();

    if (params)
    {
        var mailOptions = {
            to: '[email protected]',
            from: 'FromName <'+params.email+'>',
            subject: 'Request from ' + params.name,
            text: 'Someone has requested something! Get back to ' + params.name + ' right away!' +
                  '\n\nType: ' + params.mediaType + 
                  '\nName: ' + params.name +
                  '\nEmail: ' + params.email + 
                  '\nDedication: ' + params.dedication +
                  '\nNotes: ' + params.notes +
                  '\nCan We Post It: ' + params.socialMedia,
            attachments: [{
                filename: params.newFileName,
                // NOTE: I changed the path here to one that should work in production - deployed and got the same result
                path: '/server/uploads/'
            }]
        };

        var confirmationMailOptions = {
            // A much simpler version of above - no attachments, just text
        }

        // Send the request email
        transport.sendMail(mailOptions, function(error, info)
        {
            if(error){
                res.send({
                    nodemailerError: error, 
                    errorMessage: 'Oops! Either the email address you entered doesn\'t exist, or the interwebs are misbehaving. Try again!'
                });
            }
            else
            {
                // If booking request was successful, send the confirmation to the user
                transport.sendMail(confirmationMailOptions, function(error, info)
                {
                    if (error) {
                        console.log(error);
                    } else {
                        res.send({
                            successMessage: 'Confirmation message sent to: ' + params.email
                        });

                        req.session.destroy();
                    }
                });
            }
        });
    }
    else
    {
        res.send({paramStatus: 'destroyed'});
    }
}

person Justin    schedule 29.06.2015    source источник
comment
имя свойства path, а не filePath : github.com/andris9/Nodemailer#attachments   -  person hassansin    schedule 29.06.2015
comment
Я нашел людей, использующих оба имени свойства, поэтому попробовал оба. Тот же результат.   -  person Justin    schedule 29.06.2015
comment
Я также пытался использовать относительный путь к файлу вместо fs.   -  person Justin    schedule 29.06.2015
comment
как насчет использования content: img ?   -  person hassansin    schedule 29.06.2015
comment
Да, я пробовал использовать свойство content, а также указывать contentType.   -  person Justin    schedule 29.06.2015
comment
Мне пришло в голову, что могут быть проблемы с разрешениями или что-то в этом роде, поэтому теперь я пытаюсь назначить относительный путь к path с моего контроллера. Я не знаю, как это проверить, потому что по-прежнему нет явной ошибки, даже когда я подаю фиктивный путь.   -  person Justin    schedule 29.06.2015
comment
не может помочь, не видя остальной код. Вы можете просмотреть исходный код nodemailer, прикрепить точки останова и т. д., поскольку в нем нет явных ошибок.   -  person hassansin    schedule 29.06.2015
comment
Да, ты прав. Я выложил кучу кода, который мне не нравится, но, думаю, моя проблема может быть где угодно. И вряд ли это будет в исходниках nodemailer.   -  person Justin    schedule 29.06.2015
comment
Судя по nodemailer, он использует fs.createReadStream(content.path) который возвращает пустой буфер, если файл не существует (следовательно, вложение 0 КБ?). поэтому убедитесь, что path указывает на реальный файл, а не на каталог файлов. Попробуйте прочитать сначала с fs.createReadStream   -  person hassansin    schedule 30.06.2015
comment
Это, хотя и не проблема, привело меня к решению, которое я разместил в качестве ответа. Какое облегчение. И премного благодарен за помощь и обсуждение.   -  person Justin    schedule 30.06.2015


Ответы (1)


Я знал, что у меня правильный путь к изображению, и @hassansin указал мне правильное направление в отношении буфера (и andris9 из знаменитого nodemailer упомянул content: Buffer в версии этого вопроса, которую я разместил на странице GitHub. Что привело меня к этому рабочая версия:

var path = require('path');
var uploadDir = path.dirname(require.main.filename); 
var img = require("fs").readFileSync(uploadDir + '/uploads/' + params.newFileName);

attachments: [{
    filename: params.newFileName,
    content: new Buffer(img)
}]
person Justin    schedule 29.06.2015