So I downloaded the skpsmtpmessage pod and installed it to my project. I have a file called MailSender in the project that looks like:
import Foundation
import skpsmtpmessage
class MailSender: NSObject, SKPSMTPMessageDelegate {
static let shared = MailSender()
func sendEmail() {
let message = SKPSMTPMessage()
message.relayHost = "smtp.gmail.com"
message.login = "myemail#gmail.com"
message.pass = "password"
message.requiresAuth = true
message.wantsSecure = true
message.relayPorts = [587]
message.fromEmail = "myemail#gmail.com"
message.toEmail = "recipientemail#gmail.com"
message.subject = "subject"
let messagePart = [kSKPSMTPPartContentTypeKey: "text/plain; charset=UTF-8", kSKPSMTPPartMessageKey: "body of email"]
message.parts = [messagePart]
message.delegate = self
message.send()
}
func messageSent(_ message: SKPSMTPMessage!) {
print("Successfully sent email!")
}
func messageFailed(_ message: SKPSMTPMessage!, error: Error!) {
print("Sending email failed!")
}
}
In ContentView, I have a button that looks like:
Button("click me") {
MailSender.shared.sendEmail()
}
When I run the simulator and click the button in ContentView, I get a bunch of "*** stopping watchdog ***" messages in the output and then some additional messages that say "S: 250-smtp.gmail.com at your service, [My IP Address]", and then there's a message that says "S: 535-5.7.8 Username and Password not accepted. Learn more at", but I know that the from email and password that I'm providing are correct (it's my personal email information in my version of the project). Any help would be greatly appreciated.
By default support for external clients is off on Gmail, so login in your account and make sure you turned on some, IMAP is preferred.
Then make sure you configure properly email client
Related
Im wondering if there is a way to compose an email in Swift and have it populate fields such as CC and BCC.
Currently I am using NSSharingService and it only appears to have the options for Recipient, Subject, and Body.
I'm not married to using NSSharingService, but I would like to know a way to implement what I am trying to do.
EDIT: I am developing for Mac and not iOS
class SendEmail: NSObject {
static func send(recipient: String) {
let service = NSSharingService(named:
service.recipients = ["Recipient Goes Here"]
service.subject = "Subject Goes Here"
service.perform(withItems: ["Body Goes Here"])
}
}
This works in Swift5 (Xcode 10.2.1, macOS 10.14.5)
let url = URL(string: "mailto:to#example.com?subject=subject&cc=cc#example.com&bcc=bcc#example.com")!
NSWorkspace.shared.open(url)
I am making my own app in Swift, and wanted to include the feature of resetting passwords using Parse. My console eventually shows a successful notice, but when I go to the email to see if Parse sent the email to reset password, I don't receive anything. Would really appreciate it if you could help me sort this issue :D I've added a screenshot so that you can see what my console shows.
#IBAction func recoverPasswordButton(_ sender: Any) {
PFUser.requestPasswordResetForEmail(inBackground: emailTextField.text!, block: { (success, error) in
if self.emailTextField != nil {
self.displayAlert(title: "Check your email", message: "A link has been sent to recover your password. Follow the instructions.")
print("A link to recover your password has been sent")
} else {
var errorText = "Unknown error: please try again"
if let error = error {
errorText = error.localizedDescription
}
self.displayAlert(title: "Email is not valid", message: errorText)
}
})
}
For Email verification, You need to add the setting in the dashboard like below
The first thing is that Parse stops his support, you have to use Back4App.
I have created a Swift universal app that incorporates the MailCore2 API. It works perfectly on both debug and release mode. When I asked a friend in California to test it out, an alert view popped up with an error message. I found out that the reason for this was because I was using Google as the account I was emailing from.
Here is my code:
var smtpSession = MCOSMTPSession()
smtpSession.hostname = "smtp.gmail.com"
smtpSession.username = "matt#gmail.com"
smtpSession.password = "xxxxxxxxxxxxxxxx"
smtpSession.port = 465
smtpSession.authType = MCOAuthType.SASLPlain
smtpSession.connectionType = MCOConnectionType.TLS
smtpSession.connectionLogger = {(connectionID, type, data) in
if data != nil {
if let string = NSString(data: data, encoding: NSUTF8StringEncoding){
NSLog("Connectionlogger: \(string)")
}
}
}
var builder = MCOMessageBuilder()
builder.header.to = [MCOAddress(displayName: "Rool", mailbox: "itsrool#gmail.com")]
builder.header.from = MCOAddress(displayName: "Matt R", mailbox: "matt#gmail.com")
builder.header.subject = "My message"
builder.htmlBody = "Yo Rool, this is a test message!"
let rfc822Data = builder.data()
let sendOperation = smtpSession.sendOperationWithData(rfc822Data)
sendOperation.start { (error) -> Void in
if (error != nil) {
NSLog("Error sending email: \(error)")
} else {
NSLog("Successfully sent email!")
}
}
Google prevented the email from being sent because it thought a hijacker was trying to access my account (being that I am in a different state when I normally log in.)
My question is: Is there a way of preventing Google from blocking these emails from being sent? I would like people to be able to send emails, no matter where they are located. If this isn't possible, them is there an emailing service that doesn't prevent emails from being sent just because you (the users) are logging in from a different location?
Thanks in advance to all who reply.
this one works for me, hope it works for you too, try this,
let smtpSession:MCOSMTPSession = MCOSMTPSession()
smtpSession.hostname = "smtp.gmail.com"
smtpSession.port = 465
smtpSession.username = "abc#gmail.com"
smtpSession.password = "xxxxx"
smtpSession.authType = MCOAuthType.SASLPlain
smtpSession.connectionType = MCOConnectionType.TLS
let builder:MCOMessageBuilder = MCOMessageBuilder()
let from:MCOAddress = MCOAddress(displayName: "abc", mailbox: "abc#gmail.com")
let to:MCOAddress = MCOAddress(displayName: nil, mailbox: "abc#gmail.com")
builder.header.from = from
builder.header.to = [to]
builder.header.subject = "My Messgae"
builder.htmlBody = "This is test message"
let rcf822Data:NSData = builder.data()
let sendOperation:MCOSMTPSendOperation = smtpSession.sendOperationWithData(rcf822Data)
sendOperation.start { (error:NSError?) in
if (error != nil) {
print("Error Sending Mail : \(error)")
}else{
print("Mail Sent Successfully")
}
}
This my first project using swift. I am usin alamofire to connect the API. I have a local copy form the API I want to use for debugging - so I can set test data - because the remote API has already real data that I can't mess with.
The problem is I am getting the below error when I try to access https://localhost:8443/MyProject
Optional(Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “localhost” which could put your confidential information at risk." UserInfo=0x7fbeb8c61ff0 {NSURLErrorFailingURLPeerTrustErrorKey=, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorCodeKey=-9813, NSUnderlyingError=0x7fbeb8ea5c00 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1202.)", NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “localhost” which could put your confidential information at risk., NSErrorFailingURLKey=https://localhost:8443/myproject/api/loginUser.pdo, NSErrorFailingURLStringKey=https://localhost:8443/myproject/api/loginUser.pdo, _kCFStreamErrorDomainKey=3})
I have found many solution most of them for Objective-c as using setAllowsAnyHTTPSCertificate or using the delegate for Connection.
but I could not find an equevelent method for setAllowsAnyHTTPSCertificate in swift, and I not sure how to set the delegate to the connection while using alamofire.
any ideas what I need to do?
I know that setAllowsAnyHTTPSCertificate is private api and will cause the project to be rejected by Apple. I want to use it only while debugging then it will be removed before the publishing the project.
Thank you in advance.
You can easily override the default challenge behavior in Alamofire using the SessionDelegate override closures. Here is an example of how you can allow Alamofire to accept invalid certificates:
IMPORTANT: Please do not use this in any production code. Security is VERY important and this implementation completely disregards the security mechanisms in Alamofire. Use at your own risk!
let manager = Alamofire.Manager.sharedInstance
manager.delegate.sessionDidReceiveChallenge = { session, challenge in
var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
var credential: NSURLCredential?
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
disposition = NSURLSessionAuthChallengeDisposition.UseCredential
credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust)
} else {
if challenge.previousFailureCount > 0 {
disposition = .CancelAuthenticationChallenge
} else {
credential = manager.session.configuration.URLCredentialStorage?.defaultCredentialForProtectionSpace(challenge.protectionSpace)
if credential != nil {
disposition = .UseCredential
}
}
}
return (disposition, credential)
}
We (the Alamofire TC) are going to implement TLS pinning and several other features related to security in the Alamofire 1.3.0 release.
UPDATE
The Alamofire 1.3.0 release is out and adds MUCH better support for customizing server trust authentication challenges. For further info, please check out the Security section of the README.
Swift 3 version of #cnoon's code
manager.delegate.sessionDidReceiveChallenge = { session, challenge in
var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling
var credential: URLCredential?
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust, let trust = challenge.protectionSpace.serverTrust {
disposition = URLSession.AuthChallengeDisposition.useCredential
credential = URLCredential(trust: trust)
} else {
if challenge.previousFailureCount > 0 {
disposition = .cancelAuthenticationChallenge
} else {
credential = self.manager.session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace)
if credential != nil {
disposition = .useCredential
}
}
}
return (disposition, credential)
}
Swift 3
In my case when I use swagger client library, I changed my code to test the local server like this:
open func createSessionManager() -> Alamofire.SessionManager {
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = buildHeaders()
let serverTrustPolicies: [String: ServerTrustPolicy] = ["localhost": .disableEvaluation]
return Alamofire.SessionManager(configuration: configuration, serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))
}
Replacing with https to http of my base url. resolved the error.
I created a chat room in Quickblox, when i sends message to chatroom its offline users does not get any push notification.
To send message :
[[QBChat instance] sendMessage:#"Hey! Did you see last Liverpool match?" toRoom:liverpoolFansRoom];
Is there anything that i am doing wrong or its not enabled on Quickbolx server to sends notification on chatroom's offline users.
Thanx
Push messages does not sends automatically. If you know your recipient user's ID you can send push message manually - you should call method provided below:
[QBMessages TSendPushWithText:#"text"
toUsers:(int)userId
delegate:nil];
Swift 3 :
You can send push notifications for all user connected with the dialog using following code:
var payload = [String:String]()
payload["message"] = message.text!
payload["dialog_id"] = self.dialog.id!
do {
let data = try JSONSerialization.data(withJSONObject: payload, options: .prettyPrinted)
let message = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
var opponentIDs: [String] = []
for userId in self.dialog.occupantIDs! {
// Discard currently logged in user
if userId.uintValue != _user.id {
opponentIDs.append(String(describing: userId))
}
}
let event = QBMEvent()
event.message = message
event.usersIDs = opponentIDs.joined(separator: ",")
event.notificationType = QBMNotificationType.push
event.type = QBMEventType.oneShot
QBRequest.createEvent(event, successBlock: { (response, arrEvents) in
kprint(items: event.name ?? "")
}, errorBlock: { (errRes) in
kprint(items: errRes.error?.description ?? "")
})
} catch {
print(error.localizedDescription)
}