| | |
| | | |
| | | void makeIssueMapToIssue(Issue issue, Map<String, Object> issueMap); |
| | | |
| | | void sendCommonEmail(EmailCommonForm make); |
| | | void sendCommonEmail(EmailCommonForm make, List<MultipartFile> files); |
| | | } |
| | |
| | | import kr.wisestone.owl.domain.User; |
| | | import kr.wisestone.owl.domain.enumType.EmailType; |
| | | import org.springframework.data.jpa.repository.JpaRepository; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.util.List; |
| | | import java.util.Locale; |
| | |
| | | |
| | | void directEmail(String[] sendUsers, EmailType emailType, Map<String, Object> content, String toUser); |
| | | |
| | | void sendEmail(String subject, String content, String[] to, String[] filePaths); |
| | | void sendEmail(String subject, String content, String[] to, String[] filePaths, List<MultipartFile> multipartFiles); |
| | | |
| | | List<String> notificationUserChange(List<User> totalUsers, List<User> targetUsers); |
| | | |
| | |
| | | for(int i=0; i < sendMails.length; i++) { |
| | | sendMails[i] = CommonUtil.decryptAES128(sendMails[i]); |
| | | } |
| | | this.systemEmailService.sendEmail(emailTemplateForm.getTitle(), emailTemplateForm.getTemplate(), sendMails, null); |
| | | this.systemEmailService.sendEmail(emailTemplateForm.getTitle(), emailTemplateForm.getTemplate(), sendMails, null, null); |
| | | |
| | | this.issueHistoryService.detectSendIssueMail(IssueHistoryType.SEND, emailTemplateForm.getSendEmails(), sb); |
| | | this.issueHistoryService.addIssueHistory(issue, IssueHistoryType.SEND, sb.toString()); |
| | | } |
| | | |
| | | @Override |
| | | public void sendCommonEmail(EmailCommonForm emailCommonForm) { |
| | | public void sendCommonEmail(EmailCommonForm emailCommonForm, List<MultipartFile> multipartFiles) { |
| | | if (emailCommonForm.getSendEmails().size() < 1) { |
| | | throw new OwlRuntimeException( |
| | | this.messageAccessor.getMessage(MsgConstants.ISSUE_NOT_SEND_USER)); |
| | |
| | | for(int i=0; i < sendMails.length; i++) { |
| | | sendMails[i] = CommonUtil.decryptAES128(sendMails[i]); |
| | | } |
| | | this.systemEmailService.sendEmail(emailCommonForm.getTitle(), emailCommonForm.getDescription(), sendMails, null); |
| | | this.systemEmailService.sendEmail(emailCommonForm.getTitle(), emailCommonForm.getDescription(), sendMails, null, multipartFiles); |
| | | |
| | | if (issue != null) { |
| | | this.issueHistoryService.detectSendIssueMail(IssueHistoryType.SEND, emailCommonForm.getSendEmails(), sb); |
| | |
| | | import kr.wisestone.owl.service.UserService; |
| | | import kr.wisestone.owl.util.*; |
| | | import org.apache.commons.io.FilenameUtils; |
| | | import org.flywaydb.core.internal.util.scanner.filesystem.FileSystemResource; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | import javax.activation.DataSource; |
| | | import javax.activation.FileDataSource; |
| | | import javax.mail.SendFailedException; |
| | | import javax.mail.internet.InternetAddress; |
| | | import javax.mail.internet.MimeMessage; |
| | | import javax.mail.internet.MimeUtility; |
| | | import javax.mail.internet.*; |
| | | import java.io.IOException; |
| | | import java.util.*; |
| | | |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | import org.thymeleaf.context.Context; |
| | | import org.thymeleaf.spring5.SpringTemplateEngine; |
| | | |
| | |
| | | break; |
| | | } |
| | | |
| | | this.sendEmail(this.messageAccessor.message(mailConstants.getTitle(), locale), content, sendUsers, filePaths); |
| | | this.sendEmail(this.messageAccessor.message(mailConstants.getTitle(), locale), content, sendUsers, filePaths, null); |
| | | } |
| | | |
| | | // 이메일 템플릿 찾기 |
| | |
| | | // 이메일을 발송한다. |
| | | @Override |
| | | @Transactional(readOnly = true) |
| | | public void sendEmail(String subject, String content, String[] to, String[] filePaths) { |
| | | public void sendEmail(String subject, String content, String[] to, String[] filePaths, List<MultipartFile> multipartFiles) { |
| | | MimeMessage message = this.javaMailSender.createMimeMessage(); |
| | | |
| | | try { |
| | |
| | | messageHelper.setText(content, true); |
| | | messageHelper.setFrom(from); |
| | | messageHelper.setTo(to); |
| | | |
| | | if (multipartFiles != null && multipartFiles.size() > 0) { |
| | | for (MultipartFile file : multipartFiles) { |
| | | // 파일 첨부 |
| | | messageHelper.addAttachment(file.getOriginalFilename(), file); |
| | | } |
| | | } |
| | | |
| | | if (filePaths != null && filePaths.length > 0) { |
| | | for (String filePath : filePaths) { |
| | |
| | | // 내용이 있으면 발송 |
| | | if (!StringUtils.isEmpty(emailBuilder.toString())) { |
| | | // 이메일을 발송한다. |
| | | this.sendEmail(this.messageAccessor.message(MsgConstants.RESERVATION_EMAIL_TITLE, locale), emailBuilder.toString(), new String[]{CommonUtil.decryptAES128(sendUser)}, null); |
| | | this.sendEmail(this.messageAccessor.message(MsgConstants.RESERVATION_EMAIL_TITLE, locale), emailBuilder.toString(), new String[]{CommonUtil.decryptAES128(sendUser)}, null, null); |
| | | this.systemEmailRepository.saveAll(systemEmails); |
| | | } |
| | | } |
| | |
| | | // 내용이 있으면 발송 |
| | | if (!StringUtils.isEmpty(emailBuilder.toString())) { |
| | | // 이메일을 발송한다. |
| | | this.sendEmail(this.messageAccessor.message(MsgConstants.REALTIME_EMAIL_TITLE, locale), emailBuilder.toString(), new String[]{CommonUtil.decryptAES128(sendUser)}, null); |
| | | this.sendEmail(this.messageAccessor.message(MsgConstants.REALTIME_EMAIL_TITLE, locale), emailBuilder.toString(), new String[]{CommonUtil.decryptAES128(sendUser)}, null, null); |
| | | this.systemEmailRepository.saveAll(systemEmails); |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | // 일반 메일 발송 (사용자 직접 작성) |
| | | @RequestMapping(value = "/issue/sendCommonEmail", produces = MediaType.APPLICATION_JSON_VALUE) |
| | | @RequestMapping(value = "/issue/sendCommonEmail", method = RequestMethod.POST) |
| | | public |
| | | @ResponseBody |
| | | Map<String, Object> sendCommonEmail(@RequestBody Map<String, Map<String, Object>> params) { |
| | | Map<String, Object> sendCommonEmail(MultipartHttpServletRequest request) { |
| | | Map<String, Object> resJsonData = new HashMap<>(); |
| | | this.issueService.sendCommonEmail(EmailCommonForm.make(params.get(Constants.REQ_KEY_CONTENT))); |
| | | this.issueService.sendCommonEmail(EmailCommonForm.make(ConvertUtil.convertJsonToMap(request.getParameter(Constants.REQ_KEY_CONTENT))), request.getFiles("file")); |
| | | return this.setSuccessMessage(resJsonData); |
| | | } |
| | | |
| | | |
| | | // api 기록 조회 |
| | | @RequestMapping(value = "/api/findHistory", produces = MediaType.APPLICATION_JSON_VALUE) |
| | |
| | | formSubmit : formSubmit, // 폼 전송 |
| | | formCheck : formCheck, // 폼 체크 |
| | | addInput : addInput, |
| | | removeInput : removeInput |
| | | removeInput : removeInput, |
| | | onFileSelect : onFileSelect, // 파일 첨부 |
| | | removeUploadFile : removeUploadFile, // 업로드하려는 특정 파일을 삭제 |
| | | imageUpload : imageUpload, // 섬머노트 이미지 업로드 |
| | | |
| | | }; |
| | | |
| | | $scope.vm = { |
| | |
| | | description: "", |
| | | inputs : [0], |
| | | emails : {}, // 입력된 사용자 이메일 |
| | | files : [], // 업로드 파일 |
| | | attachedFiles : [], // 섬머노트로 파일 업로드를 할 경우 서버에서 pk를 따고 issue id와 연동 작업이 필요하다. |
| | | }, |
| | | userName : "", |
| | | autoCompletePage : { |
| | |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | // 섬머노트 이미지 업로드 |
| | | function imageUpload($files) { |
| | | var listFiles = []; |
| | | var uploadFileSize = 0; |
| | | |
| | | for (var count in $files) { |
| | | var $file = $files[count]; |
| | | |
| | | if (typeof ($file) == "object") { |
| | | uploadFileSize += $file.size; |
| | | |
| | | // 파일당 용량 제한 10MB |
| | | if ($file.size > $rootScope.fileByte.image) { |
| | | SweetAlert.error($filter("translate")("issue.capacityExceededImageFile"), $filter("translate")("issue.attachedOnlyImageFiles10mb")); // "이미지 파일 용량 초과", "10MB 이하의 이미지 파일만 첨부가 가능합니다." |
| | | listFiles = []; |
| | | break; |
| | | } |
| | | |
| | | // 여러건의 파일을 한번에 업로드할 경우 제한 300MB |
| | | if (uploadFileSize > $rootScope.fileByte.file) { |
| | | SweetAlert.error($filter("translate")("issue.capacityExceededImageFile"), $filter("translate")("issue.attachedMultipleImageFiles100mb")); // "이미지 파일 용량 초과", "여러 건의 이미지를 한번에 첨부할 경우 100MB 이하까지만 첨부가 가능합니다." |
| | | listFiles = []; |
| | | break; |
| | | } |
| | | |
| | | if (!$rootScope.checkImageType($file)) { |
| | | SweetAlert.error($filter("translate")("issue.limitImageFile"), $filter("translate")("issue.canBeUploadedOnlyImageFiles")); // "이미지 파일 제한", "이미지 파일만 업로드 가능합니다. - bmp, jpg, jpeg, png, tif" |
| | | listFiles = []; |
| | | break; |
| | | } |
| | | |
| | | if (!angular.isDefined($file.name)) { |
| | | var fileType = $file.type.split("/"); |
| | | var imageType = ""; |
| | | |
| | | if (fileType[0] === "image") { |
| | | imageType = "." + fileType[1]; |
| | | } |
| | | |
| | | $file.name = new Date().getTime() + imageType; |
| | | } |
| | | else { |
| | | if ($file.name.indexOf(';') !== -1) { |
| | | SweetAlert.error($filter("translate")("issue.nameErrorImageFile"), $filter("translate")("issue.cannotUploadFileNameSpecialCharacters")); // "이미지 파일명 오류", "파일명에 특수문자(;)가 들어가면 업로드 할 수 없습니다." |
| | | listFiles = []; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | listFiles.push($file); |
| | | } |
| | | } |
| | | |
| | | // 파일 업로드 검증을 거친 파일이 1개이상 존재할 경우에만 실행 |
| | | if (listFiles.length > 0) { |
| | | AttachedFile.add({ |
| | | method : "POST", |
| | | file : listFiles, |
| | | // data 속성으로 별도의 데이터 전송 |
| | | fields : { |
| | | content : { |
| | | workspaceId : $rootScope.user.lastWorkspaceId |
| | | } |
| | | }, |
| | | fileFormDataName : "file" |
| | | }) |
| | | .then(function (result) { |
| | | if (result.data.message.status === "success") { |
| | | angular.forEach(result.data.attachedFiles, function (fileInfo) { |
| | | $scope.vm.summerNote.editor.summernote("editor.insertImage", fileInfo.path); |
| | | $scope.vm.form.attachedFiles.push(fileInfo); |
| | | }); |
| | | } |
| | | else { |
| | | SweetAlert.error($filter("translate")("issue.errorFileUpload"), result.data.message.message); // 파일 업로드 오류 |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // 파일 업로드에 사용 |
| | | function onFileSelect($files) { |
| | | var uploadFileSize = 0; |
| | | |
| | | // 이전에 첨부한 파일이 있을 경우 전체 업로드 용량에 포함 |
| | | angular.forEach($scope.vm.form.files, function ($file) { |
| | | uploadFileSize += $file.size; |
| | | }); |
| | | |
| | | for (var count in $files) { |
| | | var $file = $files[count]; |
| | | |
| | | if (typeof ($file) == "object") { |
| | | uploadFileSize += $file.size; |
| | | |
| | | // 파일당 용량 제한 300MB |
| | | if (($file.size > $rootScope.fileByte.file) || (uploadFileSize > $rootScope.fileByte.file)) { |
| | | SweetAlert.error($filter("translate")("issue.attachmentCapacityExceeded"), $filter("translate")("issue.canAttachFileUpTo100mb")); // "첨부 파일 용량 초과", "100MB 이하까지만 파일 첨부가 가능합니다." |
| | | break; |
| | | } |
| | | |
| | | // 파일을 업로드할 때 파일 유형을 확인해주는 기능 - 허용되지 않은 확장자일 때는 첨부 금지 |
| | | if (!$rootScope.checkFileType($file)) { |
| | | SweetAlert.error($filter("translate")("issue.limitAttachmentExtensions"), $filter("translate")("issue.notAllowedAttachment")); // "첨부 파일 확장자 제한", "첨부가 허용되지 않는 파일입니다." |
| | | break; |
| | | } |
| | | |
| | | if ($file.name.indexOf(';') !== -1) { |
| | | SweetAlert.error($filter("translate")("issue.nameErrorAttachment"), $filter("translate")("issue.cannotUploadFileNameSpecialCharacters")); // "첨부 파일명 오류", "파일명에 특수문자(;)가 들어가면 업로드 할 수 없습니다." |
| | | break; |
| | | } |
| | | |
| | | $file.index = count; |
| | | $scope.vm.form.files.push($file); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 업로드 파일 삭제 |
| | | function removeUploadFile(index) { |
| | | $scope.vm.form.files.splice(index, 1); |
| | | |
| | | angular.forEach($scope.vm.form.files, function (file, index) { |
| | | file.index = index; |
| | | }); |
| | | } |
| | | |
| | | // 메일 주소 input 창 추가 버튼 |
| | |
| | | }); |
| | | |
| | | return sendEmails; |
| | | })() |
| | | })(), |
| | | attachedFileIds : (function () { |
| | | var attachedFileIds = []; |
| | | |
| | | angular.forEach($scope.vm.form.attachedFiles, function (attachedFile) { |
| | | if ($scope.vm.form.description.indexOf(attachedFile.path) !== -1) { |
| | | attachedFileIds.push(attachedFile.id); |
| | | } |
| | | }); |
| | | |
| | | return attachedFileIds; |
| | | })(), |
| | | }; |
| | | |
| | | Issue.sendCommonEmail($resourceProvider.getContent( |
| | | content, |
| | | $resourceProvider.getPageContent(0, 10))).then(function (result) { |
| | | |
| | | Issue.sendCommonEmail({ |
| | | method : "POST", |
| | | file : $scope.vm.form.files, |
| | | // data 속성으로 별도의 데이터 전송 |
| | | fields : { |
| | | content : content |
| | | }, |
| | | fileFormDataName : "file" |
| | | }).then(function (result) { |
| | | if (result.data.message.status === "success") { |
| | | SweetAlert.success($filter("translate")("issue.succeededIssueMail"), $filter("translate")("issue.sentToTheSelectedUser")); // "이슈 메일 발송 완료" |
| | | $scope.fn.cancel(); |
| | |
| | | }); |
| | | }, |
| | | sendCommonEmail : function (conditions) { |
| | | return $http.post("issue/sendCommonEmail", conditions).then(function (response) { |
| | | conditions.url = "issue/sendCommonEmail"; |
| | | return $upload.upload(conditions).progress(function (evt) { |
| | | // 파일 업로드 진행율을 표시해준다. |
| | | fileUploadProgress(evt); |
| | | |
| | | }).then(function (response) { |
| | | $log.debug("이슈 이메일 발송 결과 : ", response); |
| | | return response; |
| | | }); |
| | | } |
| | | }, |
| | | } |
| | | } |
| | | ]) |
| | |
| | | target=".note-editable"></summernote> |
| | | </div> |
| | | <small class="mt-1" translate="common.sendToPerson">다른 사용자에게 메일을 보냅니다.</small> |
| | | |
| | | <div class="form-group mgb5 mt-10"> |
| | | <label class="issue-label"><span translate="common.attachFiles">파일 첨부</span></label> |
| | | <div class="filebox input-group"> |
| | | <input class="upload-name form-control" |
| | | placeholder="{{'users.pleaseSelectFile' | translate}}" |
| | | tabindex="-1" |
| | | disabled="disabled"> |
| | | <label for="uploadFileField"><span |
| | | translate="common.selectFile">파일선택</span></label> |
| | | <input id="uploadFileField" |
| | | tabindex="-1" |
| | | type="file" |
| | | class="form-control" |
| | | multiple |
| | | ng-file-select="fn.onFileSelect($files)"> |
| | | </div> |
| | | |
| | | <div class="select2-selection__choicediv"> |
| | | <div class="select2-selection__choice2" ng-repeat="file in vm.form.files"> |
| | | <div class="select2-selection__choice2__remove" ng-click="fn.removeUploadFile($index)"> |
| | | × |
| | | </div> |
| | | <div class="ssg-items ssg-items-blocks"> |
| | | <div class="ssg-item"> |
| | | <div class="item-icon"> |
| | | <!-- 문서 --> |
| | | <i class="os-icon os-icon-file-text" ng-if="file.fileType == 'DOC'"></i> |
| | | <!-- 미디어 --> |
| | | <i class="os-icon os-icon-film" ng-if="file.fileType == 'MEDIA'"></i> |
| | | <!-- 이미지(업로드 전) --> |
| | | <i class="os-icon os-icon-documents-07" |
| | | ng-if="file.fileType == 'IMAGE'"></i> |
| | | <!-- 기타 --> |
| | | <i class="os-icon os-icon-ui-51" ng-if="file.fileType == 'ETC'"></i> |
| | | </div> |
| | | <div class="item-name"> |
| | | <small>{{file.name}}</small> |
| | | </div> |
| | | <div class="item-amount"> |
| | | ({{file.size/1024/1024 | number:2}} MB) |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </form> |
| | | </div> |
| | | |