Permalink
Browse files

Version 0.2.0

  • Loading branch information...
JLospinoso committed Nov 1, 2015
1 parent 1b88e10 commit c2444381b5a2ec3945db1a18100a1b6eae900bbb
Showing with 781 additions and 43 deletions.
  1. +2 −2 build.gradle
  2. +3 −0 config.json
  3. +1 −0 dailyc-core/build.gradle
  4. +37 −3 dailyc-core/src/main/groovy/net/lospi/dailyc/DailycConfiguration.groovy
  5. +52 −17 dailyc-core/src/main/groovy/net/lospi/dailyc/DailycManager.groovy
  6. +25 −0 dailyc-core/src/main/groovy/net/lospi/dailyc/comm/MailSender.groovy
  7. +1 −0 dailyc-core/src/main/groovy/net/lospi/dailyc/comm/MogreetSender.groovy
  8. +28 −0 dailyc-core/src/main/groovy/net/lospi/dailyc/core/EmailSubscriber.groovy
  9. +4 −0 dailyc-core/src/main/groovy/net/lospi/dailyc/core/NoEmailSubscribersException.groovy
  10. +22 −0 dailyc-core/src/main/groovy/net/lospi/dailyc/core/SentEmail.groovy
  11. +4 −0 dailyc-core/src/main/groovy/net/lospi/dailyc/persistence/BatchLoader.groovy
  12. +23 −0 dailyc-core/src/main/groovy/net/lospi/dailyc/persistence/Dao.groovy
  13. +9 −1 dailyc-core/src/main/resources/application.properties
  14. +26 −7 dailyc-core/src/test/groovy/net/lospi/dailyc/DailycManagerTest.groovy
  15. +59 −0 dailyc-core/src/test/groovy/net/lospi/dailyc/MailManagerIntegrationTest.groovy
  16. +1 −1 dailyc-core/src/test/groovy/net/lospi/dailyc/MogreetManagerIntegrationTest.groovy
  17. +11 −0 dailyc-core/src/test/groovy/net/lospi/dailyc/persistence/BatchLoaderTest.groovy
  18. +6 −1 dailyc-core/src/test/resources/config.json
  19. +21 −0 dailyc-mail/build.gradle
  20. +58 −0 dailyc-mail/src/main/java/net/lospi/mail/MailManager.java
  21. +44 −0 dailyc-mail/src/main/java/net/lospi/mail/core/EmailSendRequest.java
  22. +19 −0 dailyc-mail/src/main/java/net/lospi/mail/core/EmailSendResponse.java
  23. +13 −0 dailyc-mail/src/main/java/net/lospi/mail/core/EmailSendResponseFactory.java
  24. +10 −0 dailyc-mail/src/main/java/net/lospi/mail/multipart/JpegDataSourceFactory.java
  25. +9 −0 dailyc-mail/src/main/java/net/lospi/mail/multipart/MultipartMailFactory.java
  26. +116 −0 dailyc-mail/src/test/java/net/lospi/mail/MailManagerTest.java
  27. +58 −0 dailyc-mail/src/test/java/net/lospi/mail/core/EmailSendRequestTest.java
  28. +32 −0 dailyc-mail/src/test/java/net/lospi/mail/core/EmailSendResponseFactoryTest.java
  29. +33 −0 dailyc-mail/src/test/java/net/lospi/mail/core/EmailSendResponseTest.java
  30. +26 −0 dailyc-mail/src/test/java/net/lospi/mail/multipart/JpegDataSourceFactoryTest.java
  31. +19 −0 dailyc-mail/src/test/java/net/lospi/mail/multipart/MultipartMailFactoryTest.java
  32. BIN dailyc-mail/src/test/resources/dailyc.jpg
  33. +8 −9 mogreet/build.gradle
  34. +0 −1 mogreet/src/test/java/net/lospi/mogreet/MogreetManagerTest.java
  35. +1 −1 settings.gradle
@@ -1,8 +1,8 @@
apply plugin:'java'
apply plugin:'groovy'

version = '0.1.0'
description = 'MMS batch service'
version = '0.2.0'
description = 'A multimedia message and email batch service'

task wrapper(type: Wrapper) {
gradleVersion = '2.6'
@@ -3,6 +3,9 @@
"subscribers": [
"5551234567"
],
"emailSubscribers": [
"dailyc@lospi.net"
],
"messages": [
"Hello world!",
"Foo!"
@@ -19,6 +19,7 @@ repositories {

dependencies {
compile project(':mogreet')
compile project(':dailyc-mail')
compile ('org.springframework.boot:spring-boot-starter-actuator',
'org.codehaus.groovy:groovy-all:2.4.+',
'org.springframework:spring-context:4.+',
@@ -2,12 +2,17 @@ package net.lospi.dailyc

import groovy.json.JsonSlurper
import groovy.util.logging.Slf4j
import net.lospi.dailyc.comm.MailSender
import net.lospi.dailyc.comm.MogreetSender
import net.lospi.dailyc.comm.MogreetSubscriber
import net.lospi.dailyc.comm.MogreetUploader
import net.lospi.dailyc.persistence.BatchLoader
import net.lospi.dailyc.persistence.Dao
import net.lospi.dailyc.util.Hasher
import net.lospi.mail.core.EmailSendResponseFactory
import net.lospi.mail.MailManager
import net.lospi.mail.multipart.JpegDataSourceFactory
import net.lospi.mail.multipart.MultipartMailFactory
import net.lospi.mogreet.MogreetManager
import net.lospi.mogreet.core.AuthorizationToken
import net.lospi.mogreet.core.BaseResponse
@@ -55,11 +60,27 @@ class DailycConfiguration {
private String databaseUsername
@Value('${database.password}')
private String databasePassword
@Value('${email.userName}')
private String emailUserName
@Value('${email.password}')
private String emailPassword
@Value('${email.hostName}')
private String emailHostName
@Value('${email.sslSmtpPort}')
private String sslSmtpPort
@Value('${email.attachmentName}')
private String emailAttachmentName
@Value('${email.fromName}')
private String emailFromName
@Value('${email.toName}')
private String emailToName
@Value('${email.from}')
private String emailFrom

@Bean
public DataSource dataSource() {
new DriverManagerDataSource( driverClassName:databaseDriver, url:databaseUrl, username:databaseUsername,
password:databasePassword )
new DriverManagerDataSource(driverClassName:databaseDriver, url:databaseUrl, username:databaseUsername,
password:databasePassword)
}

@Bean
@@ -88,6 +109,16 @@ class DailycConfiguration {
getRequestEncoder, postRequestEncoder)
}

@Bean
public MailManager mailManager() {
MultipartMailFactory multipartMailFactory = new MultipartMailFactory()
EmailSendResponseFactory emailSendResponseFactory = new EmailSendResponseFactory()
JpegDataSourceFactory jpegDataSourceFactory = new JpegDataSourceFactory()
return new MailManager(emailUserName, emailPassword, emailHostName, sslSmtpPort,
emailAttachmentName, emailFromName,
emailToName, multipartMailFactory, emailSendResponseFactory, jpegDataSourceFactory)
}

@Bean
DailycManager dailycBatch() {
File configFile = new File(configPath)
@@ -99,8 +130,11 @@ class DailycConfiguration {
MogreetSender sender = new MogreetSender(manager: manager, campaignId: campaignId, from: from)
MogreetSubscriber subscriber = new MogreetSubscriber(manager: manager, campaignId: campaignId)
MogreetUploader mogreetUploader = new MogreetUploader(manager: manager)
MailManager mailManager = mailManager()
MailSender mailSender = new MailSender(from: emailFrom, mailManager: mailManager)
new DailycManager(mogreetSender: sender, mogreetSubscriber: subscriber,
mogreetUploader: mogreetUploader, dao: dao, batchLoader: batchLoader)
mogreetUploader: mogreetUploader, dao: dao,
batchLoader: batchLoader, mailSender: mailSender)
}

private AuthorizationToken makeToken() throws IOException {
@@ -1,18 +1,22 @@
package net.lospi.dailyc

import groovy.util.logging.Slf4j
import net.lospi.dailyc.comm.MailSender
import net.lospi.dailyc.comm.MogreetSender
import net.lospi.dailyc.comm.MogreetSubscriber
import net.lospi.dailyc.comm.MogreetUploader
import net.lospi.dailyc.core.EmailSubscriber
import net.lospi.dailyc.core.ImageFile
import net.lospi.dailyc.core.MessageBody
import net.lospi.dailyc.core.Subscriber
import net.lospi.dailyc.persistence.BatchLoader
import net.lospi.dailyc.persistence.Dao
import net.lospi.mail.MailManager
import net.lospi.mogreet.core.UploadResponse

@Slf4j
class DailycManager implements Runnable {
MailSender mailSender
MogreetSender mogreetSender
MogreetSubscriber mogreetSubscriber
MogreetUploader mogreetUploader
@@ -30,39 +34,48 @@ class DailycManager implements Runnable {
log.info("[+] Loaded {} messages from disk", messages.size())
def nMessages = dao.loadMessages(messages).size()
log.info("[+] {} messages updated", nMessages)
log.debug("[ ] Updating subscribers")
log.debug("[ ] Updating MMS subscribers")
def subscribers = batchLoader.subscribers
log.info("[+] Loaded {} subscribers from disk", subscribers.size())
log.info("[+] Loaded {} MMS subscribers from disk", subscribers.size())
def nSubscribers = dao.loadSubscribers(subscribers).size()
log.info("[+] {} subscribers updated", nSubscribers)
log.info("[+] {} MMS subscribers updated", nSubscribers)
log.debug("[ ] Updating email subscribers")
def emailSubscribers = batchLoader.emailSubscribers
log.info("[+] Loaded {} email subscribers from disk", emailSubscribers.size())
def nEmailSubscribers = dao.loadEmailSubscribers(emailSubscribers).size()
log.info("[+] {} email subscribers updated", nEmailSubscribers)
def nextMessage = dao.nextMessageBody()
def nextImage = dao.nextImageFile()
log.info("[ ] Next message: {}", nextMessage.contents)
log.info("[ ] Next image: {}", nextImage.name)
if(nextMessage.lastUse)
log.warn("[-] Next message has been used previously: {}", nextMessage.lastUse)
if(nextImage.lastUse)
log.warn("[-] Previous message has been used previously: {}", nextImage.lastUse)
log.warn("[-] Next image has been used previously: {}", nextImage.lastUse)
}

void run() {
def selectedFile = dao.nextImageFile()
def selectedMessage = dao.nextMessageBody()
def subscribers = dao.getSubscribers()
def emailSubscribers = dao.getEmailSubscribers()

validateInput(selectedMessage, selectedFile, subscribers)
validateInput(selectedMessage, selectedFile, subscribers, emailSubscribers)
String contentId = uploadContent(selectedFile)
int messagesSuccessful = sendMessages(subscribers, selectedMessage, selectedFile, contentId)
reportOnBatchSuccess(messagesSuccessful, subscribers)
int mmsSuccessful = sendMms(subscribers, selectedMessage, selectedFile, contentId)
int emailSuccessful = sendEmail(emailSubscribers, selectedMessage, selectedFile)
reportOnBatchSuccess(mmsSuccessful, emailSuccessful, subscribers, emailSubscribers)
}

private void reportOnBatchSuccess(int messagesSuccessful, List<Subscriber> numbers) {
if (messagesSuccessful == numbers.size()) {
private void reportOnBatchSuccess(int mmsSuccessful, int emailSuccessful,
List<Subscriber> numbers, List<EmailSubscriber> emails) {
def numberRequested = numbers.size() + emails.size()
def numberSuccessful = mmsSuccessful + emailSuccessful;
if (numberRequested == numberSuccessful) {
log.info("[+] Batch completed with all messages sent successfully.")
} else {
def numberFailed = numbers.size() - messagesSuccessful
log.error("[-] Batch completed with {} of {} messages sent successfully.", messagesSuccessful, numbers.size())
throw new RuntimeException(String.format("%d messages failed to send", numberFailed))
log.error("[-] Batch completed with {} of {} messages sent successfully.", numberSuccessful, numberRequested)
throw new RuntimeException(String.format("%d messages failed to send", numberRequested - numberSuccessful))
}
}

@@ -84,19 +97,22 @@ class DailycManager implements Runnable {
contentId
}

private void validateInput(selectedMessage, selectedFile, numbers) {
private void validateInput(selectedMessage, selectedFile, numbers, emails) {
if (!selectedMessage)
throw new RuntimeException("MessageBodyGenerator returned null message.")
if (!selectedFile)
throw new RuntimeException("ImageFileGenerator returned null ImageFile.")
if (numbers.size() == 0)
throw new RuntimeException("SubscriberGenerator returned no numbers.")
if (emails.size() == 0)
throw new RuntimeException("EmailSubscriberGenerator returned no numbers.")
log.info("[+] Selected message: \"{}\"", selectedMessage)
log.info("[+] Selected file: {}", selectedFile)
log.info("[+] {} subscribers.", numbers.size())
log.info("[+] {} MMS subscribers.", numbers.size())
log.info("[+] {} email subscribers.", numbers.size())
}

private int sendMessages(List<Subscriber> subscribers, MessageBody messageBody, ImageFile imageFile,
private int sendMms(List<Subscriber> subscribers, MessageBody messageBody, ImageFile imageFile,
String contentId) {
return subscribers.count{ subscriber ->
try {
@@ -107,11 +123,30 @@ class DailycManager implements Runnable {
def mms = dao.createSentMms(subscriber, messageBody, imageFile, date)
log.info("[+] Sent MMS \n{}", mms)
} else {
log.error("[-] Not sent to {}:\n{}\n{}", subscriber, subscribeResponse, sendResponse)
log.error("[-] MMS not sent to {}:\n{}\n{}", subscriber, subscribeResponse, sendResponse)
}
return sendResponse.successful
} catch (any) {
log.error("[-] Could not subscribe/send to {}:\n", subscriber, any.toString())
log.error("[-] Could not subscribe/send to {}: {}\n", subscriber, any.toString())
return false
}
}
}

private int sendEmail(List<EmailSubscriber> emailSubscribers, MessageBody messageBody, ImageFile imageFile) {
return emailSubscribers.count{ subscriber ->
try {
def sendResponse = mailSender.send(subscriber, messageBody, imageFile)
if (sendResponse.successful) {
Date date = new Date()
def email = dao.createSentEmail(subscriber, messageBody, imageFile, date)
log.info("[+] Sent email \n{}", email)
} else {
log.error("[-] Email not sent to {}:\n{}", subscriber, sendResponse)
}
return sendResponse.successful
} catch (any) {
log.error("[-] Could not send to {}: {}\n", subscriber, any.toString())
return false
}
}
@@ -0,0 +1,25 @@
package net.lospi.dailyc.comm

import groovy.util.logging.Slf4j
import net.lospi.dailyc.core.EmailSubscriber
import net.lospi.dailyc.core.ImageFile
import net.lospi.dailyc.core.MessageBody
import net.lospi.mail.MailManager
import net.lospi.mail.core.EmailSendRequest

@Slf4j
class MailSender {
MailManager mailManager
String from

def send(EmailSubscriber emailSubscriber, MessageBody messageBody, ImageFile imageFile) {
log.info("[ ] Sending image {} to email {}; message: {}", imageFile, emailSubscriber, messageBody)
def request = new EmailSendRequest(emailSubscriber.address, from, messageBody.contents, imageFile.image)
def result = mailManager.send(request)
if(result.successful)
log.info("[+] Success! Response from mail server: {}", result.messageResponse)
else
log.error("[-] Failure! Response from mail server: %n{}", result.messageResponse)
return result
}
}
@@ -1,6 +1,7 @@
package net.lospi.dailyc.comm

import groovy.util.logging.Slf4j
import net.lospi.dailyc.core.EmailSubscriber
import net.lospi.dailyc.core.MessageBody
import net.lospi.dailyc.core.Subscriber
import net.lospi.mogreet.MogreetManager
@@ -0,0 +1,28 @@
package net.lospi.dailyc.core

import grails.persistence.Entity

@Entity
class EmailSubscriber {
String address
Date lastUse

static hasMany = [
sentEmail : SentEmail
]

static constraints = {
lastUse(nullable: true)
}

@Override
public String toString() {
return """\
EmailSubscriber{
id=$id,
address='$address',
lastUse=$lastUse,
version=$version
}"""
}
}
@@ -0,0 +1,4 @@
package net.lospi.dailyc.core

class NoEmailSubscribersException {
}
@@ -0,0 +1,22 @@
package net.lospi.dailyc.core

import grails.persistence.Entity

@Entity
class SentEmail {
EmailSubscriber emailSubscriber
MessageBody messageBody
ImageFile imageFile
Date sentDate

@Override
public String toString() {
final StringBuilder sb = new StringBuilder("SentEmail{");
sb.append("emailSubscriber=").append(emailSubscriber);
sb.append(", messageBody=").append(messageBody);
sb.append(", imageFile=").append(imageFile);
sb.append(", sentDate=").append(sentDate);
sb.append('}');
return sb.toString();
}
}
@@ -20,6 +20,10 @@ class BatchLoader {
(List<String>) getKey("subscribers")
}

List<String> getEmailSubscribers() {
(List<String>) getKey("emailSubscribers")
}

private File getKeyFile(String key) {
String path = getKey(key)
File file = new File(path)
@@ -8,6 +8,10 @@ import net.lospi.dailyc.util.Hasher
class Dao {
Hasher hasher

List<EmailSubscriber> loadEmailSubscribers(List<String> emailSubscribers) {
emailSubscribers.collect{EmailSubscriber.findOrSaveByAddress(it)}
}

List<Subscriber> loadSubscribers(List<String> subscribers) {
subscribers.collect{Subscriber.findOrSaveByNumber(it)}
}
@@ -49,6 +53,13 @@ class Dao {
subscribers
}

List<Subscriber> getEmailSubscribers() {
def emailSubscribers = EmailSubscriber.getAll()
if(emailSubscribers.size() == 0)
throw new NoSubscribersException()
emailSubscribers
}

SentMms createSentMms(Subscriber subscriber, MessageBody messageBody, ImageFile imageFile, Date sentDate) {
SentMms sentMms = new SentMms(subscriber: subscriber, messageBody: messageBody, imageFile: imageFile,
sentDate: sentDate)
@@ -60,4 +71,16 @@ class Dao {
imageFile.save()
sentMms.save()
}

SentEmail createSentEmail(EmailSubscriber emailSubscriber, MessageBody messageBody, ImageFile imageFile, Date sentDate) {
SentEmail sentMms = new SentEmail(emailSubscriber: emailSubscriber, messageBody: messageBody, imageFile: imageFile,
sentDate: sentDate)
emailSubscriber.lastUse = sentDate
messageBody.lastUse = sentDate
imageFile.lastUse = sentDate
emailSubscriber.save()
messageBody.save()
imageFile.save()
sentMms.save()
}
}
Oops, something went wrong.

0 comments on commit c244438

Please sign in to comment.