1

I am trying to email some Entry data that they have created in CSV Format to the author/logged in user. I have a controller setup with a frontend form posting an action to the controller:

public function actionSendCSV(){
 $this->requirePostRequest();

 $entryId = craft()->request->getParam('entryId');
 $entry = craft()->elements->getElementById($entryId);

 $user = craft()->userSession->getUser();

 if ($user->id != $entry->getAuthor()->id) {
     HeaderHelper::setHeader(array('status' => 404));
     craft()->end();
 }else{
   $list = array(
     //This is test data I'll construct the entry data here
    "Peter,Griffin,Oslo,Norway",
    "Glenn,Quagmire,Oslo,Norway");
    $file = fopen("test.csv","w");
    foreach ($list as $line){
      fputcsv($file,explode(',',$line));
    }

    $email = new EmailModel();
    $email->toEmail = $user->email;
    $email->subject = 'Your CSV';
    $email->body = 'How you doin, {{ user.name }}?';

    // Im not really sure what to do next here - do I save the CSV as an asset and then link it here? 
    $email->addAttachment('path/to/csv/', 'name in e-mail.csv', 'base64', 'text/csv');

    craft()->email->sendEmail($email);
 }}

Is this the best way to handle this or should I save the entry data as CSV to my assets folder(Perhaps create a folder just for that user in the process to store all exports from them?) and send a link to users? If so what is the best method to achieve this?

Thanks!

1

For this purpose there is not such a thing like a "best" way. Every thing has advantages and disadvantages. Depending on your goal you should decide what fits best for you.

I personally prefer to have my files attached to the email so I can be sure I actually have the file on every device and I can redownload it every time. Other people might say it's better to just have a link for whatever reasons.

So I would create a temporary file and attach it to the mail like you do. Make sure to name each file separately. If you have really large entries (that need more time to generate the csv) and two authors click the button at the same time they could eventually overwrite each other. So it might be a good idea to include the author ID or something in the filename. You can delete it afterwards.

If you want to keep these files you could store them as Craft assets but i don't think this is necessary for your purpose. You could create a record if you like to track the activities. So if you need to see how many authors used that download how often you can insert it into your database.

However, the more interesting thing is how to fetch the entries and fields. Btw you know you have to parse the body content in order to replace the twig tokens?

Edit
You could use this function

 /**
 * Send Email
 *
 * @param $message string
 * @param $subject string
 * @param $mail string
 * @param array $attachments
 * @return bool
 */
public function sendMail($message, $subject, $mail, $attachments = array()){
    $adminEmail = craft()->systemSettings->getSetting('email', 'emailAddress');
    $email = new EmailModel();

    $email->fromEmail = $adminEmail;
    $email->replyTo = $adminEmail;
    $email->sender = $adminEmail;
    $email->fromName = craft()->getSiteName();
    $email->toEmail = $mail;
    $email->subject = $subject;
    $email->htmlBody = $message;

    if(is_array($attachments) && count($attachments)){
        foreach($attachments as $attachment){
            $email->addAttachment($attachment['path'], $attachment['name']);
        }
    }
    return craft()->email->sendEmail($email);
}

with

$attachment = [
    [
        'name' => "The name you want to display.csv",
        'path'  => $file // path/to/your/file
    ]
];

$subject = "Your CSV";
$email = $user->email;;
$message = craft()->templates->render('path/to/template', array(
    'username' => '...',
    // .....
));
if($this->sendMail($message, $subject, $email, $attachment)){
    // message send
}else{
    // some errors
}
  • Hi @RobinSchambach - Thanks again for replying, I think I'll go with creating the CSV on the fly - My question is how I attach that with addAttachment? Re your question of entries: In the front end form I pass an entry ID so I'm hoping I can grab the data I need to populate the CSV from that. – Graham Winston Dec 7 '17 at 9:35
  • I edited my answer with the function we usually use to send mails in all our plugins and below the usage – Robin Schambach Dec 7 '17 at 9:59
  • Thanking for taking the time Robin, that's a really great help - I'm still a little confused as to how I set the path to the file.If I'm creating it as the user submits the action where/how do i store the CSV? – Graham Winston Dec 7 '17 at 13:49
  • If you are lazy and delete the file afterwards anyway and have writing permissions to all locations you could just do $path = __DIR__ . "nameOfFile" . $user->id . ".csv"; so you create it in the same location like your script. You could as well use system paths or fetch paths from your config (eg CRAFT_STORAGE_PATH ) – Robin Schambach Dec 7 '17 at 13:51
  • Did you manage to make it work? About the how to save a file question: maybe you don't know but the fopen function creates a file if it's not found and the fputcsv stores the values in it. After you use fclose you can see the new created file. There is no save function you can see a working example here stackoverflow.com/a/4249458/5604055 – Robin Schambach Dec 7 '17 at 17:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.