Skip to content

Commit

Permalink
add API endpoints, update show.blade.php to reflect changes made in C…
Browse files Browse the repository at this point in the history
…ontroller, update README.md
  • Loading branch information
dmcbrn committed Mar 20, 2023
1 parent 7d7bb21 commit 9a2ad2c
Show file tree
Hide file tree
Showing 7 changed files with 269 additions and 53 deletions.
45 changes: 43 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,20 @@ Config contains three parameters:
```php
//name of the disk where the attachments will be saved
'disk' => env('EMAIL_LOG_DISK','email_log_attachments'),
//to prevent access to list of logged emails add a middlewares. Multiple middlewares can be used (separate by comma)

//to prevent access to list of logged emails through WEB routes add a middlewares
//multiple middlewares can be used (separate by comma)
'access_middleware' => env('EMAIL_LOG_ACCESS_MIDDLEWARE',null),
//this parameter prefixes the routes for listing of logged emails

//to prevent access to list of logged emails through API routes add a middlewares
//multiple middlewares can be used (separate by comma)
'access_middleware_api' => env('EMAIL_LOG_ACCESS_MIDDLEWARE_API',null),

//this parameter prefixes the routes for listing of logged emails using WEB routes
'routes_prefix' => env('EMAIL_LOG_ROUTES_PREFIX',''),

//this parameter prefixes the routes for listing of logged emails using API routes
'routes_prefix_api' => env('EMAIL_LOG_ROUTES_PREFIX_API',''),
```

# Usage
Expand Down Expand Up @@ -119,6 +129,37 @@ for all of the events. If you used a `prefix` in the config file then this shoul
https://example.com/your-prefix/email-log/webhooks/event
```

## Upgrade from 5.2.2 to 5.3.0 - API ENDPOINTS AVAILABLE, BREAKING CHANGE

API ENDPOINTS AVAILABLE:

New routes with JSON responses:
```
https://example.com/api/your-prefix/email-log
https://example.com/api/your-prefix/email-log/{id}
https://example.com/api/your-prefix/email-log/{id}/attachment/{attachment}
https://example.com/api/your-prefix/email-log/delete
```

BREAKING CHANGE:

The logic for presentation of attachments (on single email view: `show.blade.php`) has been moved to backend. If you are not using the default `show.blade.php` and are displaying list of attachments you should reflect these changes in your code. Namely, you no need to check if the file exists or add the attachment to the route to access it. Instead the returned data will be array with of following formats (depending if file can be found on disk or not):

```
//file can be found
[
'name' => 'filename.pdf',
'route' => 'https://example.com/api/email-log/email-id/attachment/attachment-key',
]
//file can't be found
[
'name' => 'filename.pdf',
'message' => 'file not found',
]
```

Note following: `/api` part will be dropped in html response, `email-id` is the `id` of the email, `attachment-key` is the order of attachment starting at `0`.

## Upgrade from 5.1.0 to 5.2.0 - BREAKING CHANGE

Add the following parameters to the end of the `config/email_log.php` array:
Expand Down
2 changes: 2 additions & 0 deletions config/email_log.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
return [
'disk' => env('EMAIL_LOG_ATTACHMENT_DISK','email_log_attachments'),
'access_middleware' => env('EMAIL_LOG_ACCESS_MIDDLEWARE',null),
'access_middleware_api' => env('EMAIL_LOG_ACCESS_MIDDLEWARE_API',null),
'routes_prefix' => env('EMAIL_LOG_ROUTES_PREFIX',''),
'routes_prefix_api' => env('EMAIL_LOG_ROUTES_PREFIX_API',''),
'routes_webhook_prefix' => env('EMAIL_LOG_ROUTES_WEBHOOK_PREFIX', env('EMAIL_LOG_ROUTES_PREFIX','')),
'mailgun' => [
'secret' => env('MAILGUN_SECRET', null),
Expand Down
38 changes: 38 additions & 0 deletions routes/api.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php
$accessMiddlewares = config('email_log.access_middleware_api', null)
? explode(',' , config('email_log.access_middleware_api'))
: [];

Route::group([
'prefix' => 'api/' . config('email_log.routes_prefix_api', ''),
'middleware' => array_merge(['api'], $accessMiddlewares),
], function(){
Route::get(
'/email-log',
[
'as' => 'api.email-log',
'uses' => 'Dmcbrn\LaravelEmailDatabaseLog\EmailLogController@indexApi',
]
);
Route::post(
'/email-log/delete',
[
'as' => 'api.email-log.delete-old',
'uses' => 'Dmcbrn\LaravelEmailDatabaseLog\EmailLogController@deleteOldEmailsApi',
]
);
Route::get(
'/email-log/{id}/attachment/{attachment}',
[
'as' => 'api.email-log.fetch-attachment',
'uses' => 'Dmcbrn\LaravelEmailDatabaseLog\EmailLogController@fetchAttachment',
]
);
Route::get(
'/email-log/{id}',
[
'as' => 'api.email-log.show',
'uses' => 'Dmcbrn\LaravelEmailDatabaseLog\EmailLogController@showApi',
]
);
});
43 changes: 37 additions & 6 deletions routes/web.php
Original file line number Diff line number Diff line change
@@ -1,20 +1,51 @@
<?php
$accessMiddlewares = config('email_log.access_middleware', null)
? explode(',' , config('email_log.access_middleware')) : [];
? explode(',' , config('email_log.access_middleware'))
: [];

Route::group([
'prefix' => config('email_log.routes_prefix', ''),
'middleware' => array_merge(['web'], $accessMiddlewares),
], function(){
Route::get('/email-log', ['as' => 'email-log', 'uses' => 'Dmcbrn\LaravelEmailDatabaseLog\EmailLogController@index']);
Route::post('/email-log/delete', ['as' => 'email-log.delete-old', 'uses' => 'Dmcbrn\LaravelEmailDatabaseLog\EmailLogController@deleteOldEmails']);
Route::get('/email-log/{id}/attachment/{attachment}', ['as' => 'email-log.fetch-attachment', 'uses' => 'Dmcbrn\LaravelEmailDatabaseLog\EmailLogController@fetchAttachment']);
Route::get('/email-log/{id}', ['as' => 'email-log.show', 'uses' => 'Dmcbrn\LaravelEmailDatabaseLog\EmailLogController@show']);
Route::get(
'/email-log',
[
'as' => 'email-log',
'uses' => 'Dmcbrn\LaravelEmailDatabaseLog\EmailLogController@index',
]
);
Route::post(
'/email-log/delete',
[
'as' => 'email-log.delete-old',
'uses' => 'Dmcbrn\LaravelEmailDatabaseLog\EmailLogController@deleteOldEmails',
]
);
Route::get(
'/email-log/{id}/attachment/{attachment}',
[
'as' => 'email-log.fetch-attachment',
'uses' => 'Dmcbrn\LaravelEmailDatabaseLog\EmailLogController@fetchAttachment',
]
);
Route::get(
'/email-log/{id}',
[
'as' => 'email-log.show',
'uses' => 'Dmcbrn\LaravelEmailDatabaseLog\EmailLogController@show',
]
);
});

Route::group([
'prefix' => config('email_log.routes_webhook_prefix', ''),
], function(){
//webhooks events
Route::post('/email-log/webhooks/event', ['as' => 'email-log.webhooks', 'uses' => 'Dmcbrn\LaravelEmailDatabaseLog\EmailLogController@createEvent']);
Route::post(
'/email-log/webhooks/event',
[
'as' => 'email-log.webhooks',
'uses' => 'Dmcbrn\LaravelEmailDatabaseLog\EmailLogController@createEvent',
]
);
});
180 changes: 143 additions & 37 deletions src/EmailLogController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,49 +11,52 @@ class EmailLogController extends Controller {

public function index(Request $request)
{
//validate
$request->validate([
'filterEmail' => 'string',
'filterSubject' => 'string',
]);

//get emails
$filterEmail = $request->filterEmail;
$filterSubject = $request->filterSubject;
$emails = EmailLog::with([
'events' => function($q) {
$q->select('messageId','created_at','event');
}
])
->select('id','messageId','date','from','to','subject')
->when($filterEmail, function($q) use($filterEmail) {
return $q->where('to','like','%'.$filterEmail.'%');
})
->when($filterSubject, function($q) use($filterSubject) {
return $q->where('subject','like','%'.$filterSubject.'%');
})
->orderBy('id','desc')
->paginate(20);
//get list of emails
list($emails, $filterEmail, $filterSubject) = $this->getEmailsForListing($request);

//return
return view('email-logger::index', compact('emails','filterEmail','filterSubject'));
}

public function show($id)
public function indexApi(Request $request)
{
//get list of emails
list($emails, $filterEmail, $filterSubject) = $this->getEmailsForListing($request);

//return
return response()->json($emails, 200);
}

public function show(int $id)
{
$email = EmailLog::find($id);
//get email
$email = $this->getEmail($id);

//return
return view('email-logger::show', compact('email'));
}

public function fetchAttachment($id,$attachment)
public function showApi(int $id)
{
//get email
$email = $this->getEmail($id, true);

//return
return response()->json(compact('email'), 200);
}

public function fetchAttachment(int $id, int $attachment)
{
//get email and attachments' paths
$email = EmailLog::select('id','attachments')->find($id);
$attachmentFullPath = explode(', ',$email->attachments)[$attachment];

$file = Storage::disk(config('email_log.disk'))->get(urldecode($attachmentFullPath));
$mimeType = Storage::disk(config('email_log.disk'))->mimeType(urldecode($attachmentFullPath));
//get file and mime type
$disk = Storage::disk(config('email_log.disk'));
$file = $disk->get(urldecode($attachmentFullPath));
$mimeType = $disk->mimeType(urldecode($attachmentFullPath));

//return file
return response($file, 200)->header('Content-Type', $mimeType);
}

Expand All @@ -63,31 +66,134 @@ public function createEvent(Request $request)

//check if event is valid
if(!$event)
return response('Error: Unsupported Service', 400)->header('Content-Type', 'text/plain');
return response('Error: Unsupported Service', 400)
->header('Content-Type', 'text/plain');

//validate the $request data for this $event
if(!$event->verify($request))
return response('Error: verification failed', 400)->header('Content-Type', 'text/plain');
return response('Error: verification failed', 400)
->header('Content-Type', 'text/plain');

//save event
return $event->saveEvent($request);
}

public function deleteOldEmails(Request $request)
{
//delete old emails
$message = $this->deleteEmailsBeforeDate($request);

//return
return redirect(route('email-log'))
->with('status', $message);
}

public function deleteOldEmailsApi(Request $request)
{
//delete old emails
$message = $this->deleteEmailsBeforeDate($request);

//return
return response()->json(compact('message'), 200);
}

private function getEmail(int $id)
{
//get email
$email = EmailLog::with('events')
->find($id);

//format attachments as collection
$attachments = collect();

//check if there are any attachments
$attachmentsArray = array_filter(explode(', ',$email->attachments));
if(count($attachmentsArray) > 0) {
//set up new $email->attachments values
foreach($attachmentsArray as $key => $attachment) {
//update each attachment's value depending if file can be found on disk
$fileName = basename($attachment);
if(Storage::disk(config('email_log.disk'))->exists($attachment)) {
$route = $isApi
? 'api.email-log.fetch-attachment'
: 'email-log.fetch-attachment';
$formattedAttachment = [
'name' => $fileName,
'route' => route($route, [
'id' => $email->id,
'attachment' => $key,
]),
];
} else {
$formattedAttachment = [
'name' => $fileName,
'message' => 'file not found',
];
}
$attachments->push($formattedAttachment);
}
}

//update the attachments
$email->attachments = $attachments;

//return
return $email;
}

private function getEmailsForListing(Request $request)
{
//validate
$request->validate([
'date' => 'required|date',
'filterEmail' => 'string',
'filterSubject' => 'string',
'per_page' => 'numeric',
]);

//get emails
$emails = EmailLog::select('id', 'date', 'messageId')->where('date', '<=', date("c", strtotime($request->date)))->get();
$filterEmail = $request->filterEmail;
$filterSubject = $request->filterSubject;
$emails = EmailLog::with([
'events' => function($q) {
$q->select('messageId','created_at','event');
}
])
->select('id','messageId','date','from','to','subject')
->when($filterEmail, function($q) use($filterEmail) {
return $q->where('to','like','%'.$filterEmail.'%');
})
->when($filterSubject, function($q) use($filterSubject) {
return $q->where('subject','like','%'.$filterSubject.'%');
})
->orderBy('id','desc')
->paginate($request->per_page ?: 20);

//delete attachments & emails
foreach ($emails as $email) { Storage::disk(config('email_log.disk'))->deleteDirectory($email->messageId); }
$deleted = EmailLog::destroy($emails->pluck('id'));
return [$emails, $filterEmail, $filterSubject];
}

//return
return redirect(route('email-log'))->with('status', 'Deleted ' . $deleted . ' emails logged before ' . date("r", strtotime($request->date)));
private function deleteEmailsBeforeDate(Request $request)
{
//validate
$request->validate([
'date' => 'required|date',
]);

//get emails
$date = strtotime($request->date);
$emails = EmailLog::select('id', 'date', 'messageId')
->where('date', '<=', date("c", $date))
->get();

//delete email attachments
foreach ($emails as $email) {
Storage::disk(config('email_log.disk'))
->deleteDirectory($email->messageId);
}

//delete emails
$numberOfDeletedEmails = EmailLog::destroy($emails->pluck('id'));

//return message
return 'Deleted ' . $deleted . ' emails logged on and before ' . date("r", $date);
}
}
Loading

0 comments on commit 9a2ad2c

Please sign in to comment.