# Definición del servicio mail.equip.cloud
## Requisitos
- Debe proveer servicio de correo a cuentas registradas de la empresa @equipco.app y @equipcollaboration.com en google.
- Considerar que solo se enviarán correos puntuales por procesos (1 correo a 1 destinatario), no correos masivos
- Incorporar seguridad necesaria para que el servicio solo pueda ser accesado por equipos de EquipCollaboration
- Debe ser una API que posea un endpoint para realizar el envío que reciba su input vía POST (nombre/correo destinatario, asunto, cuerpo en HTML)
- Se debe considerar registro Log de correos enviados y fallidos para finalmente reportar a Elastic
- Considerar la codificación de los test necesarios
## Casos de uso
1. Registrar un nuevo mail para utilizar.
2. Envío de mail
```
curl --header "Content-Type: application/json"
--request POST
--data '{
"senderName":"xyz",
"senderEmail":"xyz@asd.com",
"recieverEmail":"xyz@asd.com",
"subject":"Title",
"body":"<html></html>",
"apiKey":"123e4567-e89b-12d3-a456-426614174000",
"mockResult": "fail" / "succeed"
}' https://mail.equip.cloud/sendMail
```
## Diagrama general
```plantuml
```
## Definición de los componentes
1. **UFW:**
- Puerto 22 habilitado para ssh
- Puerto 443 habilitado para api
2. **Nginx:**
- Solo llamadas a través https para interacutar con el servicio
- Cualquier subdominio está bloqueado
3. **Express y código:**
- Inicialización:
```
- Se define un trasporter global. https://nodemailer.com/smtp/oauth2/#example-5
```
- Endpoint:
- **sendMail[^Second]**:
```
// Se corrobora la estructura de la llamada,
// Si los atributos son erroneos, se devuelve un código 422 con reason: "Wrong parameters"
// Se extraen los atributos
// Se corrobora que exista el senderEmail en la BD
// Si no éxiste, se genera un error 400 con reason: "Sender email not available"
// Se corrobora el valor del apiKey en la BD
// Si no existe, se devuelve un código 405 con reason: "Not allowed"
// Si es de desarrollo,
// se corrobora el valor del atributo mockResult,
// si es fail, se responde con error 500 y reason: "Failed for development reasons"
// si es succeed, se envía un código 200 y reason: "Succeded for development reasons.".
// Si es de producción
// Se obtiene token activo
// Se utiliza el transporte con el access_token obtenido https://nodemailer.com/smtp/oauth2/#example-5
// Recibe la respuesta,
// Si se envió el mail, se envía la respuesta 200 con reason: mail sent.
// Si no se envió el mail, se responde un 500 con reason: "Failed to send mail. Error Message: ""
```
4. **Base de datos:**
- Crear una BD que se active con docker-compose
- Tablas:
- User [id, mail: String, refreshToken: String]
- Version [version: Int, prodKey: String, devKey: String]
- ¿Cómo permito la query para obtener el refresh_token de un mail, cuando ?
- Procesos en npm start:
- createContainer
- updateDB
- LoadDB
- saveDB
5. **Pm2:** Para mantener en ejecución el servicio y poder reiniciarlo.
6. **.env:** Utilizar librerías para guardar el client_id, client_secret
7. **Joi:** Corroborar esquema de llamadas a la api para enviar mail.
8. **Jest:** Para generar los tests unitarios que corroboran las funciones.
9. **Winston:** Se genera un access.log con todas las llamadas al servicio y su respectiva respuesta. Si es error, debe tener ese log level y debe incluirse el error completo.
10. **Filebeat:** Enviar los registros al servidor de elastic.
11. **Metricbeat:** Enviar datos para monitorear consumo de recursos.
## Proceso Manual para ingresar un nuevo mail[^first]
1. Se debe ingresar a https://developers.google.com/oauthplayground
2. Use your own OAuth credentials box
3. Then paste in the client id and secret
4. On the left, under the Select & authorize APIs section, find Gmail API v1 and select https://mail.google.com/. Alternately, you can also type https://mail.google.com/ into the Input your own scopes field. Now click Authorize APIs.
5. click allow so that Google OAuth 2.0 Playground has access to your Google account.
6. After being redirected back to the OAuth 2.0 Playground, click the Exchange authorization code for tokens button under the Exchange authorization code for tokens section. Once the refresh and access token is generated, copy the refresh token.
7. Ingresar en la base de datos, un nuevo usuario con ese refresh token.
8. Reiniciar el servicio
## Limitaciones
- ["Gmail has a limit of 2000 recipients a day"](https://nodemailer.com/usage/using-gmail/)
## Documentación
- https://developers.google.com/gmail/api/reference/rest
- https://developers.google.com/identity/protocols/oauth2/web-server
- https://github.com/googleapis/google-api-nodejs-client
- https://dev.to/chandrapantachhetri/sending-emails-securely-using-node-js-nodemailer-smtp-gmail-and-oauth2-g3a
- https://medium.com/@nickroach_50526/sending-emails-with-node-js-using-smtp-gmail-and-oauth2-316fe9c790a1
- https://nodemailer.com/usage/using-gmail/
- https://nodemailer.com/smtp/oauth2/
[^first]: Footnote Aquí hay dos opciones: realizar la otorgación de acceso a la aplicación de forma manual o de forma automática. Para este diseño se asume la forma manual, debido a que es la más sencilla y ya está implementada.
[^Second]: Footnote Aquí hay distintas alternativas, a) ¿Quién genera el access token? 1. Nosotros a través de la librería googleapis, 2. NodeMailer. b) ¿Qué tipo de transporte usar? 1. Uno por cada usuario, hay que mantenerlo en memoria, 2. Usar un trasporte de nuestra aplicación y al enviar mails se agrega la autenticación de cada usuario.