Emails versenden.

master
Markus Kreth 6 years ago
parent f2bbb78292
commit 1de86c5cdd
  1. 93
      src/main/java/de/kreth/vaadin/clubhelper/vaadinclubhelper/email/Email.java
  2. 8
      src/main/java/de/kreth/vaadin/clubhelper/vaadinclubhelper/email/EmailCommand.java
  3. 23
      src/main/java/de/kreth/vaadin/clubhelper/vaadinclubhelper/email/EmailException.java
  4. 77
      src/main/java/de/kreth/vaadin/clubhelper/vaadinclubhelper/email/MuttEmailCommand.java
  5. 11
      src/main/java/de/kreth/vaadin/clubhelper/vaadinclubhelper/ui/components/menu/LoggedinMenuitemState.java
  6. 1
      src/main/java/de/kreth/vaadin/clubhelper/vaadinclubhelper/ui/navigation/ClubhelperNavigation.java
  7. 3
      src/main/java/de/kreth/vaadin/clubhelper/vaadinclubhelper/ui/navigation/ClubhelperViews.java
  8. 223
      src/main/java/de/kreth/vaadin/clubhelper/vaadinclubhelper/ui/navigation/ExportEmails.java
  9. 290
      src/main/java/de/kreth/vaadin/clubhelper/vaadinclubhelper/ui/navigation/SendEmails.java

@ -0,0 +1,93 @@
package de.kreth.vaadin.clubhelper.vaadinclubhelper.email;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class Email {
private final String subject;
private final String message;
private final List<String> emails;
private final List<Path> attachements;
private Email(Builder builder) {
this.subject = builder.subject;
this.message = builder.message;
this.emails = Collections.unmodifiableList(builder.emails);
this.attachements = Collections.unmodifiableList(builder.attachements);
}
public String getSubject() {
return subject;
}
public String getMessage() {
return message;
}
public List<String> getEmails() {
return emails;
}
public List<Path> getAttachements() {
return attachements;
}
@Override
public String toString() {
return "Email [subject=" + subject + ", emails=" + emails + "]";
}
public static class Builder {
private String subject;
private String message;
private List<String> emails;
private List<Path> attachements;
private Builder() {
emails = new ArrayList<>();
attachements = new ArrayList<>();
}
public Builder setSubject(String subject) {
this.subject = subject;
return this;
}
public Builder setMessage(String message) {
this.message = message;
return this;
}
public Builder addEmails(List<String> emails) {
this.emails.addAll(emails);
return this;
}
public boolean addAttachment(Path e) {
return attachements.add(e);
}
public boolean addAttachments(Collection<? extends Path> c) {
return attachements.addAll(c);
}
public Email build() {
return new Email(this);
}
}
public static Builder builder() {
return new Builder();
}
}

@ -0,0 +1,8 @@
package de.kreth.vaadin.clubhelper.vaadinclubhelper.email;
import java.io.IOException;
public interface EmailCommand {
void send(Email email) throws IOException;
}

@ -0,0 +1,23 @@
package de.kreth.vaadin.clubhelper.vaadinclubhelper.email;
import java.util.List;
public class EmailException extends RuntimeException {
private final List<String> failedEmails;
public EmailException(String message, List<String> failedEmails) {
super(message);
this.failedEmails = failedEmails;
}
public EmailException(String message, List<String> failedEmails, Throwable cause) {
super(message, cause);
this.failedEmails = failedEmails;
}
public List<String> getFailedEmails() {
return failedEmails;
}
}

@ -0,0 +1,77 @@
package de.kreth.vaadin.clubhelper.vaadinclubhelper.email;
import java.io.File;
import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.stereotype.Component;
@Component
public class MuttEmailCommand implements EmailCommand {
@Override
public void send(Email email) throws IOException {
final List<String> arguments = createArguments(email);
final List<String> errors = new ArrayList<>();
File log = new File("email.log");
List<String> adresses = email.getEmails();
for (String adress : adresses) {
List<ProcessBuilder> builders = new ArrayList<>();
ProcessBuilder echoProcess = new ProcessBuilder("echo", quote(email.getMessage()));
echoProcess.redirectOutput(Redirect.PIPE);
builders.add(echoProcess);
List<String> command = new ArrayList<>(arguments);
command.add(adress);
ProcessBuilder procBuilder = new ProcessBuilder(command);
procBuilder.redirectOutput(log);
builders.add(procBuilder);
List<Process> pipeline = ProcessBuilder.startPipeline(builders);
Process last = pipeline.get(pipeline.size() - 1);
try {
// new BufferedReader(new InputStreamReader(last.getInputStream())).lines().collect(Collectors.counting());
int result = last.waitFor();
if (result != 0) {
errors.add(adress);
}
}
catch (InterruptedException e) {
}
}
if (errors.isEmpty() == false) {
throw new RuntimeException("Errors: " + errors);
}
}
private String quote(String text) {
return "\"" + text + "\"";
}
private List<String> createArguments(Email email) {
List<String> arguments = new ArrayList<>();
arguments.add("mutt");
arguments.add("-s");
arguments.add(quote(email.getSubject()));
//
// List<Path> attachements = email.getAttachements();
// for (Path path : attachements) {
// arguments.add("-a");
// arguments.add(quote(path.toAbsolutePath().toString()));
// }
arguments = Collections.unmodifiableList(arguments);
return arguments;
}
}

@ -61,6 +61,8 @@ class LoggedinMenuitemState extends LoggedOffState {
private MenuItem exportEmailsMenuItem; private MenuItem exportEmailsMenuItem;
private MenuItem sendEmailsMenuItem;
public LoggedinMenuitemState(ApplicationContext context, UI ui, Supplier<ZonedDateTime> startProvider, public LoggedinMenuitemState(ApplicationContext context, UI ui, Supplier<ZonedDateTime> startProvider,
Supplier<ZonedDateTime> endProvider, BiConsumer<String, JasperPrint> printConsumer) { Supplier<ZonedDateTime> endProvider, BiConsumer<String, JasperPrint> printConsumer) {
super(context, startProvider, endProvider, printConsumer); super(context, startProvider, endProvider, printConsumer);
@ -124,9 +126,14 @@ class LoggedinMenuitemState extends LoggedOffState {
createMeldungMenuItem = createMeldungCommand.addTo(editMenu); createMeldungMenuItem = createMeldungCommand.addTo(editMenu);
CommandWrapper exportEmails = new CommandWrapper(new SwitchViewCommand(context, "Emails exportieren", CommandWrapper exportEmails = new CommandWrapper(new SwitchViewCommand(context, "Emails exportieren",
VaadinIcons.CALENDAR, ClubhelperViews.ExportEmails)); VaadinIcons.ENVELOPE_O, ClubhelperViews.ExportEmails));
exportEmailsMenuItem = exportEmails.addTo(editMenu); exportEmailsMenuItem = exportEmails.addTo(editMenu);
CommandWrapper sendMail = new CommandWrapper(new SwitchViewCommand(context, "Emails senden",
VaadinIcons.ENVELOPE_O, ClubhelperViews.SendEmails));
sendEmailsMenuItem = sendMail.addTo(editMenu);
CommandWrapper deleeteEvent = new CommandWrapper(new DeleteEventCommand(this::deleteEvent)); CommandWrapper deleeteEvent = new CommandWrapper(new DeleteEventCommand(this::deleteEvent));
deleteMenuItem = deleeteEvent.addTo(editMenu); deleteMenuItem = deleeteEvent.addTo(editMenu);
@ -151,6 +158,7 @@ class LoggedinMenuitemState extends LoggedOffState {
} }
exportEmailsMenuItem.setEnabled(false); exportEmailsMenuItem.setEnabled(false);
sendEmailsMenuItem.setEnabled(false);
if (ClubhelperViews.PersonEditView == view) { if (ClubhelperViews.PersonEditView == view) {
openPersonMenuItem.setChecked(true); openPersonMenuItem.setChecked(true);
@ -160,6 +168,7 @@ class LoggedinMenuitemState extends LoggedOffState {
calendarMenuItem.setChecked(true); calendarMenuItem.setChecked(true);
calendarMenuItem.setEnabled(false); calendarMenuItem.setEnabled(false);
exportEmailsMenuItem.setEnabled(true); exportEmailsMenuItem.setEnabled(true);
sendEmailsMenuItem.setEnabled(true);
} }
else if (ClubhelperViews.EventDetails.equals(view)) { else if (ClubhelperViews.EventDetails.equals(view)) {
eventDetailItem.setChecked(true); eventDetailItem.setChecked(true);

@ -86,6 +86,7 @@ public class ClubhelperNavigation implements ApplicationContextAware {
navi.addView(ClubhelperViews.LoginUI.name(), new LoginUI(personBusiness, securityGroupVerifier)); navi.addView(ClubhelperViews.LoginUI.name(), new LoginUI(personBusiness, securityGroupVerifier));
navi.addView(ClubhelperViews.PersonEditView.name(), personEdit); navi.addView(ClubhelperViews.PersonEditView.name(), personEdit);
navi.addView(ClubhelperViews.EventDetails.name(), new EventDetails(context)); navi.addView(ClubhelperViews.EventDetails.name(), new EventDetails(context));
navi.addView(ClubhelperViews.SendEmails.name(), new SendEmails(context, true));
navi.addView(ClubhelperViews.ExportEmails.name(), new ExportEmails(context)); navi.addView(ClubhelperViews.ExportEmails.name(), new ExportEmails(context));
page.addBrowserWindowResizeListener(ev -> { page.addBrowserWindowResizeListener(ev -> {

@ -10,7 +10,8 @@ public enum ClubhelperViews {
EventDetails, EventDetails,
PersonEditView, PersonEditView,
ExportEmails, ExportEmails,
LoginUI; LoginUI,
SendEmails;
public static ClubhelperViews byState(String state) { public static ClubhelperViews byState(String state) {
if (state.isBlank()) { if (state.isBlank()) {

@ -1,230 +1,11 @@
package de.kreth.vaadin.clubhelper.vaadinclubhelper.ui.navigation; package de.kreth.vaadin.clubhelper.vaadinclubhelper.ui.navigation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import com.vaadin.data.HasValue.ValueChangeEvent; public class ExportEmails extends SendEmails {
import com.vaadin.data.provider.DataProvider;
import com.vaadin.data.provider.ListDataProvider;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.shared.ui.ContentMode;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.SelectionMode;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.VerticalLayout;
import de.kreth.vaadin.clubhelper.vaadinclubhelper.business.PersonBusiness;
import de.kreth.vaadin.clubhelper.vaadinclubhelper.dao.GroupDao;
import de.kreth.vaadin.clubhelper.vaadinclubhelper.data.Contact;
import de.kreth.vaadin.clubhelper.vaadinclubhelper.data.GroupDef;
import de.kreth.vaadin.clubhelper.vaadinclubhelper.data.Person;
import de.kreth.vaadin.clubhelper.vaadinclubhelper.ui.components.menu.ClubhelperMenuBar;
import de.kreth.vaadin.clubhelper.vaadinclubhelper.ui.components.menu.MenuItemStateFactory;
public class ExportEmails extends VerticalLayout implements View {
private PersonBusiness personBusiness;
private List<GroupDef> allGroups;
private Set<GroupDef> selected;
private ListDataProvider<EmailHolder> dataProvider;
private final List<EmailHolder> items;
private MenuItemStateFactory stateFactory;
private TextArea asText;
public ExportEmails(ApplicationContext context) { public ExportEmails(ApplicationContext context) {
super(context, false);
this.stateFactory = context.getBean(MenuItemStateFactory.class);
this.personBusiness = context.getBean(PersonBusiness.class);
allGroups = context.getBean(GroupDao.class).listAll();
selected = new HashSet<>();
items = new ArrayList<>();
dataProvider = DataProvider.ofCollection(items);
}
@Override
public void enter(ViewChangeEvent event) {
View.super.enter(event);
ClubhelperMenuBar menubar = new ClubhelperMenuBar(stateFactory.currentState());
HorizontalLayout groupCheck = new HorizontalLayout();
for (GroupDef groupDef : allGroups) {
CheckBox box = new CheckBox(groupDef.getName());
box.setData(groupDef);
if (groupDef.hasValidId() && groupDef.getId() == 1) {
box.setValue(true);
selected.add(groupDef);
} }
box.addValueChangeListener(this::groupBoxEvent);
groupCheck.addComponent(box);
}
Grid<EmailHolder> grid = new Grid<>();
grid.addColumn(EmailHolder::getPrename).setCaption("Vorname");
grid.addColumn(EmailHolder::getSurname).setCaption("Nachname");
grid.addColumn(EmailHolder::getEmail).setCaption("Emailadresse");
grid.setSelectionMode(SelectionMode.MULTI);
grid.setDataProvider(dataProvider);
asText = new TextArea("Emails als Text");
asText.setWidth(10, Unit.CM);
asText.setWordWrap(false);
asText.setRows(25);
asText.setEnabled(false);
addComponent(menubar);
addComponent(new Label("<H1>Export von Emailadressen</H1>", ContentMode.HTML));
addComponent(groupCheck);
addComponent(new HorizontalLayout(grid, asText));
refreshData();
}
private void groupBoxEvent(ValueChangeEvent<Boolean> event) {
CheckBox box = (CheckBox) event.getComponent();
GroupDef groupDef = (GroupDef) box.getData();
Boolean checked = box.getValue();
if (Boolean.TRUE.equals(checked)) {
selected.add(groupDef);
}
else {
selected.remove(groupDef);
}
refreshData();
}
private void refreshData() {
items.clear();
personBusiness.listAll().stream()
.filter(this::matchGroupSelection)
.map(this::getEmails)
.forEach(items::addAll);
dataProvider.refreshAll();
StringBuilder text = new StringBuilder();
for (EmailHolder emailHolder : items) {
if (text.length() > 0) {
text.append(",\n");
}
text.append(emailHolder.getEmail());
}
asText.setValue(text.toString());
}
private boolean matchGroupSelection(Person p) {
Set<GroupDef> personGroups = p.getGroups();
boolean contains = false;
for (GroupDef g : selected) {
if (personGroups.contains(g)) {
contains = true;
break;
}
}
return contains;
}
private Collection<EmailHolder> getEmails(Person person) {
List<Contact> emails = new ArrayList<>();
List<Contact> contacts = person.getContacts();
for (Contact contact : contacts) {
if (Contact.Type.EMAIL.getName().equals(contact.getType())) {
emails.add(contact);
}
}
Set<EmailHolder> holders = new HashSet<>();
for (Contact c : emails) {
holders.add(new EmailHolder(person, c));
}
return holders;
}
private class EmailHolder {
private final Person person;
private final Contact contact;
public EmailHolder(Person person, Contact contact) {
super();
this.person = person;
this.contact = contact;
}
public String getEmail() {
return contact.getValue();
}
public String getPrename() {
return person.getPrename();
}
public String getSurname() {
return person.getSurname();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getEnclosingInstance().hashCode();
result = prime * result + ((contact.getValue() == null) ? 0 : contact.getValue().hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
EmailHolder other = (EmailHolder) obj;
if (!getEnclosingInstance().equals(other.getEnclosingInstance())) {
return false;
}
if (contact.getValue() == null) {
if (other.contact.getValue() != null) {
return false;
}
}
else if (!contact.getValue().equals(other.contact.getValue())) {
return false;
}
return true;
}
@Override
public String toString() {
return contact.getValue();
}
private ExportEmails getEnclosingInstance() {
return ExportEmails.this;
}
}
} }

@ -0,0 +1,290 @@
package de.kreth.vaadin.clubhelper.vaadinclubhelper.ui.navigation;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.context.ApplicationContext;
import com.vaadin.data.HasValue.ValueChangeEvent;
import com.vaadin.data.provider.DataProvider;
import com.vaadin.data.provider.ListDataProvider;
import com.vaadin.icons.VaadinIcons;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.shared.ui.ContentMode;
import com.vaadin.ui.Button;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.SelectionMode;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import de.kreth.vaadin.clubhelper.vaadinclubhelper.business.PersonBusiness;
import de.kreth.vaadin.clubhelper.vaadinclubhelper.dao.GroupDao;
import de.kreth.vaadin.clubhelper.vaadinclubhelper.data.Contact;
import de.kreth.vaadin.clubhelper.vaadinclubhelper.data.GroupDef;
import de.kreth.vaadin.clubhelper.vaadinclubhelper.data.Person;
import de.kreth.vaadin.clubhelper.vaadinclubhelper.email.Email;
import de.kreth.vaadin.clubhelper.vaadinclubhelper.email.EmailCommand;
import de.kreth.vaadin.clubhelper.vaadinclubhelper.ui.components.menu.ClubhelperMenuBar;
import de.kreth.vaadin.clubhelper.vaadinclubhelper.ui.components.menu.MenuItemStateFactory;
public class SendEmails extends VerticalLayout implements View {
private PersonBusiness personBusiness;
private List<GroupDef> allGroups;
private Set<GroupDef> selected;
private ListDataProvider<EmailHolder> dataProvider;
private final List<EmailHolder> items;
private MenuItemStateFactory stateFactory;
private TextArea asText;
private boolean withSend;
private final EmailCommand emailCommand;
public SendEmails(ApplicationContext context, boolean withSend) {
this.stateFactory = context.getBean(MenuItemStateFactory.class);
this.personBusiness = context.getBean(PersonBusiness.class);
allGroups = context.getBean(GroupDao.class).listAll();
selected = new HashSet<>();
items = new ArrayList<>();
dataProvider = DataProvider.ofCollection(items);
this.withSend = withSend;
if (withSend) {
this.emailCommand = context.getBean(EmailCommand.class);
}
else {
this.emailCommand = null;
}
}
@Override
public void enter(ViewChangeEvent event) {
View.super.enter(event);
ClubhelperMenuBar menubar = new ClubhelperMenuBar(stateFactory.currentState());
HorizontalLayout groupCheck = new HorizontalLayout();
for (GroupDef groupDef : allGroups) {
CheckBox box = new CheckBox(groupDef.getName());
box.setData(groupDef);
if (groupDef.hasValidId() && groupDef.getId() == 1) {
box.setValue(true);
selected.add(groupDef);
}
box.addValueChangeListener(this::groupBoxEvent);
groupCheck.addComponent(box);
}
Grid<EmailHolder> grid = new Grid<>();
grid.addColumn(EmailHolder::getPrename).setCaption("Vorname");
grid.addColumn(EmailHolder::getSurname).setCaption("Nachname");
grid.addColumn(EmailHolder::getEmail).setCaption("Emailadresse");
grid.setSelectionMode(SelectionMode.MULTI);
grid.setDataProvider(dataProvider);
asText = new TextArea("Emails als Text");
asText.setWidth(10, Unit.CM);
asText.setWordWrap(false);
asText.setRows(25);
asText.setEnabled(false);
addComponent(menubar);
addComponent(new Label("<H1>Export von Emailadressen</H1>", ContentMode.HTML));
addComponent(groupCheck);
if (withSend) {
addSending();
}
addComponent(new HorizontalLayout(grid, asText));
refreshData();
}
private void addSending() {
Label subjectLbl = new Label("Betreff");
TextField subject = new TextField();
TextArea body = new TextArea();
body.setWidth(25, Unit.CM);
body.setWordWrap(false);
body.setRows(10);
TextArea errorMessage = new TextArea();
errorMessage.setWidth(25, Unit.CM);
Button send = new Button("Senden", VaadinIcons.ENVELOPE_O);
send.addClickListener(ev -> {
List<String> adresses = items.stream()
.map(EmailHolder::getEmail)
.collect(Collectors.toList());
Email email = Email.builder()
.setSubject(subject.getValue())
.setMessage(body.getValue())
.addEmails(adresses)
.build();
try {
emailCommand.send(email);
}
catch (IOException e) {
StringWriter out = new StringWriter();
PrintWriter writer = new PrintWriter(out);
e.printStackTrace(writer);
errorMessage.setValue(errorMessage.getValue() + "\n" + e.getMessage() + "\n" + out.toString());
}
});
addComponent(subjectLbl);
addComponent(subject);
addComponent(body);
addComponent(send);
addComponent(errorMessage);
}
private void groupBoxEvent(ValueChangeEvent<Boolean> event) {
CheckBox box = (CheckBox) event.getComponent();
GroupDef groupDef = (GroupDef) box.getData();
Boolean checked = box.getValue();
if (Boolean.TRUE.equals(checked)) {
selected.add(groupDef);
}
else {
selected.remove(groupDef);
}
refreshData();
}
private void refreshData() {
items.clear();
personBusiness.listAll().stream()
.filter(this::matchGroupSelection)
.map(this::getEmails)
.forEach(items::addAll);
dataProvider.refreshAll();
StringBuilder text = new StringBuilder();
for (EmailHolder emailHolder : items) {
if (text.length() > 0) {
text.append(",\n");
}
text.append(emailHolder.getEmail());
}
asText.setValue(text.toString());
}
private boolean matchGroupSelection(Person p) {
Set<GroupDef> personGroups = p.getGroups();
boolean contains = false;
for (GroupDef g : selected) {
if (personGroups.contains(g)) {
contains = true;
break;
}
}
return contains;
}
private Collection<EmailHolder> getEmails(Person person) {
List<Contact> emails = new ArrayList<>();
List<Contact> contacts = person.getContacts();
for (Contact contact : contacts) {
if (Contact.Type.EMAIL.getName().equals(contact.getType())) {
emails.add(contact);
}
}
Set<EmailHolder> holders = new HashSet<>();
for (Contact c : emails) {
holders.add(new EmailHolder(person, c));
}
return holders;
}
private class EmailHolder {
private final Person person;
private final Contact contact;
public EmailHolder(Person person, Contact contact) {
super();
this.person = person;
this.contact = contact;
}
public String getEmail() {
return contact.getValue();
}
public String getPrename() {
return person.getPrename();
}
public String getSurname() {
return person.getSurname();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getEnclosingInstance().hashCode();
result = prime * result + ((contact.getValue() == null) ? 0 : contact.getValue().hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
EmailHolder other = (EmailHolder) obj;
if (!getEnclosingInstance().equals(other.getEnclosingInstance())) {
return false;
}
if (contact.getValue() == null) {
if (other.contact.getValue() != null) {
return false;
}
}
else if (!contact.getValue().equals(other.contact.getValue())) {
return false;
}
return true;
}
@Override
public String toString() {
return contact.getValue();
}
private SendEmails getEnclosingInstance() {
return SendEmails.this;
}
}
}
Loading…
Cancel
Save