diff --git a/identity-service/sequelize/migrations/20220711214812-add-deliverability.js b/identity-service/sequelize/migrations/20220711214812-add-deliverability.js new file mode 100644 index 00000000000..eb70e683fcf --- /dev/null +++ b/identity-service/sequelize/migrations/20220711214812-add-deliverability.js @@ -0,0 +1,17 @@ +'use strict' + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.addColumn( + 'Users', + 'isEmailDeliverable', { + type: Sequelize.BOOLEAN, + defaultValue: true + } + ) + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.removeColumn('Users', 'isEmailDeliverable') + } +} diff --git a/identity-service/src/models/user.js b/identity-service/src/models/user.js index 518d45dc18b..fb700f7081c 100644 --- a/identity-service/src/models/user.js +++ b/identity-service/src/models/user.js @@ -45,6 +45,11 @@ module.exports = (sequelize, DataTypes) => { allowNull: false, defaultValue: false }, + isEmailDeliverable: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: true + }, // this is the last time we have an activity for this user // could be updated whenever we relay a tx on behalf of them lastSeenDate: { diff --git a/identity-service/src/notifications/sendDownloadAppEmails.js b/identity-service/src/notifications/sendDownloadAppEmails.js index 25931f4714f..e57f11771ad 100644 --- a/identity-service/src/notifications/sendDownloadAppEmails.js +++ b/identity-service/src/notifications/sendDownloadAppEmails.js @@ -23,7 +23,8 @@ async function processDownloadAppEmail (expressApp, audiusLibs) { } // Get all users who have not signed in mobile and not been sent native mobile email within 2 days let now = moment() - let twoDayAgo = now.clone().subtract(2, 'days').format() + let twoDaysAgo = now.clone().subtract(2, 'days').format() + let fiveDaysAgo = now.clone().subtract(5, 'days').format() let emailUsersWalletAddress = await models.UserEvents.findAll({ attributes: ['walletAddress'], @@ -31,7 +32,8 @@ async function processDownloadAppEmail (expressApp, audiusLibs) { hasSignedInNativeMobile: false, hasSentDownloadAppEmail: false, createdAt: { - [models.Sequelize.Op.lte]: twoDayAgo + [models.Sequelize.Op.lte]: twoDaysAgo, + [models.Sequelize.Op.gt]: fiveDaysAgo } } }).map(x => x.walletAddress) diff --git a/identity-service/src/notifications/sendNotificationEmails.js b/identity-service/src/notifications/sendNotificationEmails.js index f38da22a5be..a28415f97d2 100644 --- a/identity-service/src/notifications/sendNotificationEmails.js +++ b/identity-service/src/notifications/sendNotificationEmails.js @@ -205,7 +205,8 @@ async function processEmailNotifications (expressApp, audiusLibs) { where: { blockchainUserId: { [models.Sequelize.Op.in]: allUsersWithUnseenNotifications - } + }, + isEmailDeliverable: true } }) diff --git a/identity-service/src/routes/user.js b/identity-service/src/routes/user.js index 828d13fbcd8..6b125528a57 100644 --- a/identity-service/src/routes/user.js +++ b/identity-service/src/routes/user.js @@ -1,7 +1,9 @@ +const axios = require('axios') const models = require('../models') const { handleResponse, successResponse, errorResponseBadRequest } = require('../apiHelpers') const authMiddleware = require('../authMiddleware') const captchaMiddleware = require('../captchaMiddleware') +const config = require('../config') module.exports = function (app) { /** @@ -27,12 +29,26 @@ module.exports = function (app) { const IP = req.headers['x-forwarded-for'] || req.connection.remoteAddress try { + let isEmailDeliverable = true + try { + const checkValidEmailUrl = `https://api.mailgun.net/v4/address/validate?address=${encodeURIComponent(email)}` + const checkEmailResponse = await axios.get(checkValidEmailUrl, { + auth: { + username: 'api', password: config.get('mailgunApiKey') + } + }) + isEmailDeliverable = checkEmailResponse.data.result === 'deliverable' || checkEmailResponse.data.result === 'unknown' + } catch (err) { + req.logger.error(`Unable to fetch validate email from mailgun for ${email}`, err) + } + await models.User.create({ email, // Store non checksummed wallet address walletAddress: body.walletAddress.toLowerCase(), lastSeenDate: Date.now(), - IP + IP, + isEmailDeliverable }) return successResponse()