001/*-
002 * #%L
003 * HAPI FHIR Subscription Server
004 * %%
005 * Copyright (C) 2014 - 2024 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.jpa.subscription.match.deliver.email;
021
022import ca.uhn.fhir.context.FhirContext;
023import ca.uhn.fhir.jpa.model.entity.StorageSettings;
024import ca.uhn.fhir.jpa.subscription.match.deliver.BaseSubscriptionDeliverySubscriber;
025import ca.uhn.fhir.jpa.subscription.model.CanonicalSubscription;
026import ca.uhn.fhir.jpa.subscription.model.ResourceDeliveryMessage;
027import ca.uhn.fhir.jpa.subscription.model.ResourceModifiedMessage;
028import ca.uhn.fhir.rest.api.EncodingEnum;
029import com.google.common.annotations.VisibleForTesting;
030import org.apache.commons.lang3.StringUtils;
031import org.slf4j.Logger;
032import org.slf4j.LoggerFactory;
033import org.springframework.beans.factory.annotation.Autowired;
034
035import java.util.ArrayList;
036import java.util.List;
037import java.util.Optional;
038
039import static org.apache.commons.lang3.StringUtils.defaultString;
040import static org.apache.commons.lang3.StringUtils.isNotBlank;
041import static org.apache.commons.lang3.StringUtils.trim;
042
043public class SubscriptionDeliveringEmailSubscriber extends BaseSubscriptionDeliverySubscriber {
044        private Logger ourLog = LoggerFactory.getLogger(SubscriptionDeliveringEmailSubscriber.class);
045
046        @Autowired
047        private StorageSettings myStorageSettings;
048
049        @Autowired
050        private FhirContext myCtx;
051
052        private IEmailSender myEmailSender;
053
054        @Autowired
055        public SubscriptionDeliveringEmailSubscriber(IEmailSender theEmailSender) {
056                myEmailSender = theEmailSender;
057        }
058
059        @Override
060        public void handleMessage(ResourceDeliveryMessage theMessage) throws Exception {
061                CanonicalSubscription subscription = theMessage.getSubscription();
062
063                // The Subscription.endpoint is treated as the email "to"
064                String endpointUrl = subscription.getEndpointUrl();
065                List<String> destinationAddresses = new ArrayList<>();
066                String[] destinationAddressStrings = StringUtils.split(endpointUrl, ",");
067                for (String next : destinationAddressStrings) {
068                        next = processEmailAddressUri(next);
069                        if (isNotBlank(next)) {
070                                destinationAddresses.add(next);
071                        }
072                }
073
074                String payload = "";
075                if (isNotBlank(subscription.getPayloadString())) {
076                        EncodingEnum encoding = EncodingEnum.forContentType(subscription.getPayloadString());
077                        if (encoding != null) {
078                                payload = getPayloadStringFromMessageOrEmptyString(theMessage);
079                        }
080                }
081
082                String from = processEmailAddressUri(
083                                defaultString(subscription.getEmailDetails().getFrom(), myStorageSettings.getEmailFromAddress()));
084                String subjectTemplate =
085                                defaultString(subscription.getEmailDetails().getSubjectTemplate(), provideDefaultSubjectTemplate());
086
087                EmailDetails details = new EmailDetails();
088                details.setTo(destinationAddresses);
089                details.setFrom(from);
090                details.setBodyTemplate(payload);
091                details.setSubjectTemplate(subjectTemplate);
092                details.setSubscription(subscription.getIdElement(myFhirContext));
093
094                myEmailSender.send(details);
095        }
096
097        private String processEmailAddressUri(String next) {
098                next = trim(defaultString(next));
099                if (next.startsWith("mailto:")) {
100                        next = next.substring("mailto:".length());
101                }
102                return next;
103        }
104
105        private String provideDefaultSubjectTemplate() {
106                return "HAPI FHIR Subscriptions";
107        }
108
109        public void setEmailSender(IEmailSender theEmailSender) {
110                myEmailSender = theEmailSender;
111        }
112
113        @VisibleForTesting
114        public IEmailSender getEmailSender() {
115                return myEmailSender;
116        }
117
118        /**
119         * Get the payload string, fetch it from the DB when the payload is null.
120         */
121        private String getPayloadStringFromMessageOrEmptyString(ResourceDeliveryMessage theMessage) {
122                String payload = theMessage.getPayloadString();
123
124                if (theMessage.getPayload(myCtx) != null) {
125                        return payload;
126                }
127
128                Optional<ResourceModifiedMessage> inflatedMessage =
129                                inflateResourceModifiedMessageFromDeliveryMessage(theMessage);
130                if (inflatedMessage.isEmpty()) {
131                        return "";
132                }
133
134                payload = inflatedMessage.get().getPayloadString();
135                return payload;
136        }
137}