<commit_before>/**
 * Copyright (c) 2012 <NAME> (born 1979)
 */

package debiki

import akka.actor._
import akka.actor.Actor._
import akka.util.duration._
import com.amazonaws.AmazonClientException
import com.amazonaws.auth.BasicAWSCredentials
import com.amazonaws.services.simpleemail._
import com.amazonaws.services.simpleemail.model._
import com.debiki.v0._
import java.{util => ju}
import play.api._
import play.api.libs.iteratee._
import play.api.libs.concurrent._
import play.api.Play.current
import Prelude._


/**
 * Starts a single email sending actor.
 *
 * BUG: SHOULD terminate it before shutdown, in a manner that
 * doesn't accidentally forget forever to send some emails.
 */
object Mailer {

  def startNewActor(daoFactory: DaoFactory): ActorRef = {
    val actorRef = Akka.system.actorOf(Props(
       new Mailer(daoFactory)), name = "EmailActor")
    Akka.system.scheduler.schedule(0 seconds, 20 seconds, actorRef, "SendMail")
    actorRef
  }

}


/**
 * Loads notifications with emails pending from the database,
 * constructs and sends those emails.
 *
 * Updates the notfs so no one else also attempts to construct and send
 * the same emails. Saves the sent emails in the database, together with
 * Amazon Web Service's (AWS) Simple Email Service (SES) message id.
 * The message id identifies the email in bounce/rejection/complaint emails
 * from e.g. the recipient's email system.
 *
 * As of right now, only sends emails. Does not handle incoming mail (there is
 * no incoming mail, instead such mail ends up in a certain Google Domains
 * account instead, namely support at debiki dot se (as of today 2012-03-30).
 *
 * Thread safe.
 */
class Mailer(val daoFactory: DaoFactory) extends Actor {


  val logger = play.api.Logger("app.mailer")


  private val _awsClient = {
    val accessKeyId = "AKIAJ4OCRAEOPEWEYTNQ"
    val secretKey = "<KEY>"
    new AmazonSimpleEmailServiceClient(
       new BasicAWSCredentials(accessKeyId, secretKey))
  }


  def receive = {
    case "SendMail" =>
      val notfsToMail =
        daoFactory.systemDao.loadNotfsToMailOut(
           delayInMinutes = 0, numToLoad = 11)
      logger.debug("Loaded "+ notfsToMail.notfsByTenant.size +
         " notfs, to "+ notfsToMail.usersByTenantAndId.size +" users.")
      _trySendEmailNotfs(notfsToMail)

    /*
    case Bounce/Rejection/Complaint/Other =>
     */
  }


  /**
   * Sends email notifications, for all tenants and notifications specified.
   *
   * Perhaps good reading:
   * http://colinmackay.co.uk/blog/2011/11/18/handling-bounces-on-amazon-ses/
   */
  def _trySendEmailNotfs(notfsToMail: NotfsToMail) {

    for {
      (tenantId, tenantNotfs) <- notfsToMail.notfsByTenant
      notfsByUserId: Map[String, Seq[NotfOfPageAction]] =
         tenantNotfs.groupBy(_.recipientUserId)
      (userId, userNotfs) <- notfsByUserId
    }{
      logger.debug("Considering "+ userNotfs.size +" notfs to user "+ userId)

      val tenantDao = daoFactory.buildTenantDao(
         QuotaConsumers(tenantId = tenantId))
      val tenant = tenantDao.loadTenant()
      val userOpt = notfsToMail.usersByTenantAndId.get(tenantId -> userId)
<commit_msg>Change log level to trace.<commit_after>/**
 * Copyright (c) 2012 <NAME> (born 1979)
 */

package debiki

import akka.actor._
import akka.actor.Actor._
import akka.util.duration._
import com.amazonaws.AmazonClientException
import com.amazonaws.auth.BasicAWSCredentials
import com.amazonaws.services.simpleemail._
import com.amazonaws.services.simpleemail.model._
import com.debiki.v0._
import java.{util => ju}
import play.api._
import play.api.libs.iteratee._
import play.api.libs.concurrent._
import play.api.Play.current
import Prelude._


/**
 * Starts a single email sending actor.
 *
 * BUG: SHOULD terminate it before shutdown, in a manner that
 * doesn't accidentally forget forever to send some emails.
 */
object Mailer {

  def startNewActor(daoFactory: DaoFactory): ActorRef = {
    val actorRef = Akka.system.actorOf(Props(
       new Mailer(daoFactory)), name = "EmailActor")
    Akka.system.scheduler.schedule(0 seconds, 20 seconds, actorRef, "SendMail")
    actorRef
  }

}


/**
 * Loads notifications with emails pending from the database,
 * constructs and sends those emails.
 *
 * Updates the notfs so no one else also attempts to construct and send
 * the same emails. Saves the sent emails in the database, together with
 * Amazon Web Service's (AWS) Simple Email Service (SES) message id.
 * The message id identifies the email in bounce/rejection/complaint emails
 * from e.g. the recipient's email system.
 *
 * As of right now, only sends emails. Does not handle incoming mail (there is
 * no incoming mail, instead such mail ends up in a certain Google Domains
 * account instead, namely support at debiki dot se (as of today 2012-03-30).
 *
 * Thread safe.
 */
class Mailer(val daoFactory: DaoFactory) extends Actor {


  val logger = play.api.Logger("app.mailer")


  private val _awsClient = {
    val accessKeyId = "AKIAJ4OCRAEOPEWEYTNQ"
    val secretKey = "<KEY>"
    new AmazonSimpleEmailServiceClient(
       new BasicAWSCredentials(accessKeyId, secretKey))
  }


  def receive = {
    case "SendMail" =>
      val notfsToMail =
        daoFactory.systemDao.loadNotfsToMailOut(
           delayInMinutes = 0, numToLoad = 11)
      logger.trace("Loaded "+ notfsToMail.notfsByTenant.size +
         " notfs, to "+ notfsToMail.usersByTenantAndId.size +" users.")
      _trySendEmailNotfs(notfsToMail)

    /*
    case Bounce/Rejection/Complaint/Other =>
     */
  }


  /**
   * Sends email notifications, for all tenants and notifications specified.
   *
   * Perhaps good reading:
   * http://colinmackay.co.uk/blog/2011/11/18/handling-bounces-on-amazon-ses/
   */
  def _trySendEmailNotfs(notfsToMail: NotfsToMail) {

    for {
      (tenantId, tenantNotfs) <- notfsToMail.notfsByTenant
      notfsByUserId: Map[String, Seq[NotfOfPageAction]] =
         tenantNotfs.groupBy(_.recipientUserId)
      (userId, userNotfs) <- notfsByUserId
    }{
      logger.debug("Considering "+ userNotfs.size +" notfs to user "+ userId)

      val tenantDao = daoFactory.buildTenantDao(
         QuotaConsumers(tenantId = tenantId))
      val tenant = tenantDao.loadTenant()
      val userOpt = notfsToMail.usersByTenantAndId.get(tenantId -> userId)

{'fraction_non_alphanumeric': 0.0978346767820452, 'fraction_numerical': 0.010115378536431168, 'mean_word_length': 3.4879432624113473, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '319460', 'n_tokens_mistral': 2067, 'n_tokens_neox': 1966, 'n_words': 552}