<p>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.</p>

<p>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.</p>

<p>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. </p>

<p>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.</p>

<p>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? </p>

<p><strong>Edit</strong><br>
You could use this function</p>

<pre><code> /**
 * 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()-&gt;systemSettings-&gt;getSetting('email', 'emailAddress');
    $email = new EmailModel();

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

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

<p>with</p>

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

$subject = "Your CSV";
$email = $user-&gt;email;;
$message = craft()-&gt;templates-&gt;render('path/to/template', array(
    'username' =&gt; '...',
    // .....
));
if($this-&gt;sendMail($message, $subject, $email, $attachment)){
    // message send
}else{
    // some errors
}
</code></pre>

CC BY-SA 3.0
2017-12-07T09:35:41.593Z
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
CC BY-SA 3.0
2017-12-07T09:59:05.207Z
I edited my answer with the function we usually use to send mails in all our plugins and below the usage
Robin Schambach
CC BY-SA 3.0
2017-12-07T13:49:04.810Z
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
CC BY-SA 3.0
2017-12-07T13:51:19.347Z
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
CC BY-SA 3.0
2017-12-07T17:26:01.980Z
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 https://stackoverflow.com/a/4249458/5604055
Robin Schambach
CC BY-SA 3.0
2018-02-13T13:53:24.667Z
We ended up requiring a few extra features and hired a freelancer to create a custom plugin. Thanks for sending this through and sorry for the late reply!
Graham Winston
CC BY-SA 3.0
2017-12-07T05:52:47.533Z
2017-12-07T10:28:34.273Z
2017-12-07T10:28:34.273Z
Robin Schambach
<p>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:</p>

<pre><code>public function actionSendCSV(){
 $this-&gt;requirePostRequest();

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

 $user = craft()-&gt;userSession-&gt;getUser();

 if ($user-&gt;id != $entry-&gt;getAuthor()-&gt;id) {
     HeaderHelper::setHeader(array('status' =&gt; 404));
     craft()-&gt;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-&gt;toEmail = $user-&gt;email;
    $email-&gt;subject = 'Your CSV';
    $email-&gt;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-&gt;addAttachment('path/to/csv/', 'name in e-mail.csv', 'base64', 'text/csv');

    craft()-&gt;email-&gt;sendEmail($email);
 }}
</code></pre>

<p>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?</p>

<p>Thanks!</p>

<emails><controller><entrymodel><usermodel><csv>
Save Entry Data as CSV and Email it to the Author / Logged in User
# Save Entry Data as CSV and Email it to the Author / Logged in User

(Asked by: username_0 on 2017-12-06)

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!

**Tags:** emails, controller, entrymodel, usermodel, csv


---

## 1 answers

### Answer by username_1 on 2017-12-07. Score: 2

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
}

> **Comments:**
> **username_0**: 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.  
> **username_1**: I edited my answer with the function we usually use to send mails in all our plugins and below the usage  
> **username_0**: 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?  
> **username_1**: 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` )  
> **username_1**: 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 https://stackoverflow.com/a/4249458/5604055  
> **username_0**: We ended up requiring a few extra features and hired a freelancer to create a custom plugin. Thanks for sending this through and sorry for the late reply!  

---

