Compose Ionic 5 emails with attachments (free source)
Let’s build the ionic 5 emails application where we can compose an email and we can also add attachment to this email.
It will basically use native email application of your device when you click on the send email button.
We are going to use the cordova email-composer plugin to just compose the email with required input fields.
We will also use the capacitor camera API to add the attachment to our email. The capacitor camera API is very easy to use and I found it more useful than cordova camera plugin.
Live Demo
Create the ionic 5 email application
Run the following command to create your application or if you are using your existing project then skip this step.
ionic start ionic-email sidemenu --type=angular
Now, your basic project is ready.
Run the following commands to generate required pages and services.
ionic g page pages/email-composer
ionic g service services/file/file
Install the ionic Cordova email composer
For updated info about cli commands checkout official docs.
npm install cordova-plugin-email-composer
npm install @ionic-native/email-composer
ionic cap sync
It will help us to compose the email and open our native email application to send that email.
Install the Capacitor Camera API
You can checkout capacitor official docs for latest information.
npm install @capacitor/camera
npx cap sync
This API requires storage permissions while built for android. The androidManifest.xml
will be found at the following path.
android/app/src/main/AndroidManifest.xml
If currently you don’t have this path then don’t worry it will automatically be added to your project, when you run the capacitor commands to build for android.
We need to paste the below permissions to this xml file.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Build an email compose form
Now, let’s start with our first page of the application.
We are not going to change our side menu, it is the same as provided by the ionic start template. Because it’s not the purpose of our tutorial.
We will simply use the folder.page.ts
to demonstrate the inbox but you can modify it if you want.
Our major focus is on email composer, so, we just have added some basic static stuff to this page and added a compose email button.
This button will navigate us to email composer form. That’s important.
Open the create-email.module.ts
and add the email-composer to the provider array.
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { IonicModule } from '@ionic/angular'; import { CreateEmailPageRoutingModule } from './create-email-routing.module'; import { CreateEmailPage } from './create-email.page'; import { EmailComposer } from '@ionic-native/email-composer/ngx'; @NgModule({ imports: [ CommonModule, FormsModule, ReactiveFormsModule, IonicModule, CreateEmailPageRoutingModule, ], declarations: [CreateEmailPage], providers: [EmailComposer] }) export class CreateEmailPageModule {}
Now, we have used the angular forms here to get the email related inputs, validate them. Then we are using an email composer to send the data to our native email application.
import { Component } from '@angular/core'; import { FormGroup, FormControl, Validators, FormBuilder } from '@angular/forms'; import { EmailComposer, EmailComposerOptions } from '@ionic-native/email-composer/ngx'; import { FileService } from 'src/app/services/file/file.service'; @Component({ selector: 'app-create-email', templateUrl: './create-email.page.html', styleUrls: ['./create-email.page.scss'], }) export class CreateEmailPage { showOtherTo: boolean = false; emailForm: FormGroup; attachments: any = []; formErrors: any = {}; constructor( private emailComposer : EmailComposer, private formBuilder : FormBuilder, public fileService: FileService ) { console.log(this.emailComposer); this.emailForm = this.formBuilder.group({ to : new FormControl('', Validators.compose([ Validators.required, Validators.email, Validators.maxLength(50) ])), cc : new FormControl('', Validators.compose([ Validators.email, Validators.maxLength(50) ])), bcc : new FormControl('', Validators.compose([ Validators.email, Validators.maxLength(50) ])), subject : new FormControl('', Validators.compose([ Validators.required, Validators.maxLength(50) ])), body : new FormControl('', Validators.compose([ Validators.required, Validators.maxLength(500) ])), }) } sendEmail() { console.log(this.emailForm.value); if ( !this.emailForm.valid ) { console.error('Invalid form is not accepted!'); return false; } let files = []; this.fileService.files.forEach(file => { files.push(file.path); }); let email: EmailComposerOptions = { ...this.emailForm.value, attachments : files, isHtml: true } // Send a text message using default options this.emailComposer.open(email); } selectFile() { this.fileService.selectImage(); } deleteAttachment( i: number ) { console.info(`Delete attachment with index -> ${i}`); if ( this.fileService.files[i] ) { this.fileService.files.splice(i, 1); } } getError( input : string ) { const errors = this.emailForm.controls[input].errors || {}; const messages = { required : `(${input}) field is required`, email : `(${input}) field should be a valid email`, maxlength : `(${input}) field should be less than ` } for (let error of Object.keys(errors)) { if (messages[error]) { if ( error === 'maxlength' || error === 'minlength' ) { this.formErrors[input] = messages[error] + errors[error]['requiredLength'] + ' chars'; } else { this.formErrors[input] = messages[error]; } } else { console.error(`${error} - equivalent message not found!`); } console.log(errors); } if ( Object.keys(errors).length === 0 ) { this.formErrors[input] = null; } } }
Add attachment to ionic 5 emails
We are using the capacitor camera API to add the attachment to our email. But we don’t need to add this camera to our module file and providers array. It is directly accessible in the application.
We are using a file service here, as we have already created it in the first step. So, just import the file service to the email-composer page.
import { Injectable, NgZone } from '@angular/core'; import { ActionSheetController, Platform } from '@ionic/angular'; import { Camera, CameraResultType, CameraSource } from '@capacitor/camera'; @Injectable({ providedIn: 'root' }) export class FileService { files: any = []; constructor( private actionSheetCtrl: ActionSheetController, private plt: Platform, private zone: NgZone ) { } async selectImage() { const actionSheet = await this.actionSheetCtrl.create({ header: "Select Image source", buttons: [{ text: 'Select from gallery', icon: !this.plt.is('ios') ? 'image' : null, handler: () => { this.takePicture(CameraSource.Photos); } }, { text: 'Take a pic', icon: !this.plt.is('ios') ? 'camera' : null, handler: () => { this.takePicture(CameraSource.Camera); } }, { text: 'Cancel', icon: !this.plt.is('ios') ? 'close' : null, role: 'cancel' } ] }); await actionSheet.present(); } async takePicture(sourceType: CameraSource) { const capturedPhoto = await Camera.getPhoto({ resultType: CameraResultType.Uri, source: sourceType, quality: 60 }); this.zone.run(() => { this.files.unshift({ path: capturedPhoto.path, src: capturedPhoto.webPath }); }) console.log(this.files); } }
In the file service, we have imported the capacitor Camera, CameraResultType and CameraSource.
We are using an action-sheet-controller to get the user’s choice of file source like camera or gallery. Then, we are getting the file and updating our files property.
But, we have to update our files property in the ngZone
otherwise it won’t be able to update the view part of the email composer form.
We are adding the attached images in the card form and the user can remove them by using the remove button given on that card.
At the end when the user clicks on the send-Email button, it will add the attached files to the email-composer object and send them to native email application.
That’s it. How to send emails using the ionic 5 application? Or ionic 5 emails application basic tutorial.
Hope you enjoy the tutorial. Source code link is given with the live demo screen.
See you in the next learning journey.