1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "nsIPrefService.h"
7 #include "nsIPrefBranch.h"
8 #include "nsSmtpServer.h"
9 #include "nsNetUtil.h"
10 #include "nsIAuthPrompt.h"
11 #include "nsMsgUtils.h"
12 #include "nsIMsgAccountManager.h"
13 #include "nsMsgBaseCID.h"
14 #include "nsISmtpService.h"
15 #include "nsMsgCompCID.h"
16 #include "nsILoginInfo.h"
17 #include "nsILoginManager.h"
18 #include "nsMemory.h"
19 #include "nsIObserverService.h"
20
21 NS_IMPL_ADDREF(nsSmtpServer)
NS_IMPL_RELEASE(nsSmtpServer)22 NS_IMPL_RELEASE(nsSmtpServer)
23 NS_INTERFACE_MAP_BEGIN(nsSmtpServer)
24 NS_INTERFACE_MAP_ENTRY(nsISmtpServer)
25 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
26 NS_INTERFACE_MAP_ENTRY(nsIObserver)
27 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISmtpServer)
28 NS_INTERFACE_MAP_END
29
30 nsSmtpServer::nsSmtpServer() : mKey("") {
31 m_logonFailed = false;
32 getPrefs();
33 }
34
~nsSmtpServer()35 nsSmtpServer::~nsSmtpServer() {}
36
Init()37 nsresult nsSmtpServer::Init() {
38 // We need to know when the password manager changes.
39 nsCOMPtr<nsIObserverService> observerService =
40 mozilla::services::GetObserverService();
41 NS_ENSURE_TRUE(observerService, NS_ERROR_UNEXPECTED);
42
43 observerService->AddObserver(this, "passwordmgr-storage-changed", false);
44 observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
45
46 return NS_OK;
47 }
48
49 NS_IMETHODIMP
Observe(nsISupports * aSubject,const char * aTopic,const char16_t * aData)50 nsSmtpServer::Observe(nsISupports* aSubject, const char* aTopic,
51 const char16_t* aData) {
52 // When the state of the password manager changes we need to clear the
53 // password from the cache in case the user just removed it.
54 if (strcmp(aTopic, "passwordmgr-storage-changed") == 0) {
55 // Check that the notification is for this server.
56 nsCOMPtr<nsILoginInfo> loginInfo = do_QueryInterface(aSubject);
57 if (loginInfo) {
58 nsAutoString hostnameInfo;
59 loginInfo->GetHostname(hostnameInfo);
60 nsAutoCString hostname;
61 GetHostname(hostname);
62 nsAutoCString fullName;
63 fullName = "smtp://"_ns + hostname;
64 if (!fullName.Equals(NS_ConvertUTF16toUTF8(hostnameInfo))) return NS_OK;
65 }
66 m_password.Truncate();
67 } else if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
68 // Now remove ourselves from the observer service as well.
69 nsCOMPtr<nsIObserverService> observerService =
70 mozilla::services::GetObserverService();
71 NS_ENSURE_TRUE(observerService, NS_ERROR_UNEXPECTED);
72
73 observerService->RemoveObserver(this, "passwordmgr-storage-changed");
74 observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
75 }
76
77 return NS_OK;
78 }
79
80 NS_IMETHODIMP
GetKey(char ** aKey)81 nsSmtpServer::GetKey(char** aKey) {
82 if (!aKey) return NS_ERROR_NULL_POINTER;
83 if (mKey.IsEmpty())
84 *aKey = nullptr;
85 else
86 *aKey = ToNewCString(mKey);
87 return NS_OK;
88 }
89
90 NS_IMETHODIMP
SetKey(const char * aKey)91 nsSmtpServer::SetKey(const char* aKey) {
92 NS_ASSERTION(aKey, "Bad key pointer");
93 mKey = aKey;
94 return getPrefs();
95 }
96
getPrefs()97 nsresult nsSmtpServer::getPrefs() {
98 nsresult rv;
99 nsCOMPtr<nsIPrefService> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
100 if (NS_FAILED(rv)) return rv;
101
102 nsAutoCString branchName;
103 branchName.AssignLiteral("mail.smtpserver.");
104 branchName += mKey;
105 branchName.Append('.');
106 rv = prefs->GetBranch(branchName.get(), getter_AddRefs(mPrefBranch));
107 if (NS_FAILED(rv)) return rv;
108
109 if (!mDefPrefBranch) {
110 branchName.AssignLiteral("mail.smtpserver.default.");
111 rv = prefs->GetBranch(branchName.get(), getter_AddRefs(mDefPrefBranch));
112 if (NS_FAILED(rv)) return rv;
113 }
114
115 return NS_OK;
116 }
117
118 // This function is intentionally called the same as in nsIMsgIncomingServer.
OnUserOrHostNameChanged(const nsACString & oldName,const nsACString & newName,bool hostnameChanged)119 nsresult nsSmtpServer::OnUserOrHostNameChanged(const nsACString& oldName,
120 const nsACString& newName,
121 bool hostnameChanged) {
122 // Reset password so that users are prompted for new password for the new
123 // user/host.
124 (void)ForgetPassword();
125
126 return NS_OK;
127 }
128
129 NS_IMETHODIMP
GetHostname(nsACString & aHostname)130 nsSmtpServer::GetHostname(nsACString& aHostname) {
131 nsCString result;
132 nsresult rv = mPrefBranch->GetCharPref("hostname", result);
133 if (NS_FAILED(rv))
134 aHostname.Truncate();
135 else
136 aHostname = result;
137
138 return NS_OK;
139 }
140
141 NS_IMETHODIMP
SetHostname(const nsACString & aHostname)142 nsSmtpServer::SetHostname(const nsACString& aHostname) {
143 nsCString oldName;
144 nsresult rv = GetHostname(oldName);
145 NS_ENSURE_SUCCESS(rv, rv);
146
147 // A few things to take care of if we're changing the hostname.
148 if (!oldName.Equals(aHostname, nsCaseInsensitiveCStringComparator)) {
149 rv = OnUserOrHostNameChanged(oldName, aHostname, true);
150 NS_ENSURE_SUCCESS(rv, rv);
151 }
152
153 if (!aHostname.IsEmpty())
154 return mPrefBranch->SetCharPref("hostname", aHostname);
155
156 // If the pref value is already empty, ClearUserPref will return
157 // NS_ERROR_UNEXPECTED, so don't check the rv here.
158 (void)mPrefBranch->ClearUserPref("hostname");
159 return NS_OK;
160 }
161
162 NS_IMETHODIMP
GetDescription(nsACString & aDescription)163 nsSmtpServer::GetDescription(nsACString& aDescription) {
164 nsCString temp;
165 mPrefBranch->GetCharPref("description", temp);
166 aDescription.Assign(temp);
167 return NS_OK;
168 }
169
170 NS_IMETHODIMP
SetDescription(const nsACString & aDescription)171 nsSmtpServer::SetDescription(const nsACString& aDescription) {
172 if (!aDescription.IsEmpty())
173 return mPrefBranch->SetCharPref("description", aDescription);
174 else
175 mPrefBranch->ClearUserPref("description");
176 return NS_OK;
177 }
178
179 // if GetPort returns 0, it means default port
180 NS_IMETHODIMP
GetPort(int32_t * aPort)181 nsSmtpServer::GetPort(int32_t* aPort) {
182 NS_ENSURE_ARG_POINTER(aPort);
183 if (NS_FAILED(mPrefBranch->GetIntPref("port", aPort))) *aPort = 0;
184 return NS_OK;
185 }
186
187 NS_IMETHODIMP
SetPort(int32_t aPort)188 nsSmtpServer::SetPort(int32_t aPort) {
189 if (aPort) return mPrefBranch->SetIntPref("port", aPort);
190
191 mPrefBranch->ClearUserPref("port");
192 return NS_OK;
193 }
194
195 NS_IMETHODIMP
GetDisplayname(char ** aDisplayname)196 nsSmtpServer::GetDisplayname(char** aDisplayname) {
197 nsresult rv;
198 NS_ENSURE_ARG_POINTER(aDisplayname);
199
200 nsCString hostname;
201 rv = mPrefBranch->GetCharPref("hostname", hostname);
202 if (NS_FAILED(rv)) {
203 *aDisplayname = nullptr;
204 return NS_OK;
205 }
206 int32_t port;
207 rv = mPrefBranch->GetIntPref("port", &port);
208 if (NS_FAILED(rv)) port = 0;
209
210 if (port) {
211 hostname.Append(':');
212 hostname.AppendInt(port);
213 }
214
215 *aDisplayname = ToNewCString(hostname);
216 return NS_OK;
217 }
218
219 NS_IMETHODIMP
GetSocketType(int32_t * socketType)220 nsSmtpServer::GetSocketType(int32_t* socketType) {
221 NS_ENSURE_ARG_POINTER(socketType);
222 getIntPrefWithDefault("try_ssl", socketType, 0);
223 return NS_OK;
224 }
225
226 NS_IMETHODIMP
SetSocketType(int32_t socketType)227 nsSmtpServer::SetSocketType(int32_t socketType) {
228 return mPrefBranch->SetIntPref("try_ssl", socketType);
229 }
230
231 NS_IMETHODIMP
GetHelloArgument(nsACString & aHelloArgument)232 nsSmtpServer::GetHelloArgument(nsACString& aHelloArgument) {
233 nsresult rv;
234 rv = mPrefBranch->GetCharPref("hello_argument", aHelloArgument);
235 if (NS_FAILED(rv)) {
236 rv = mDefPrefBranch->GetCharPref("hello_argument", aHelloArgument);
237 if (NS_FAILED(rv)) aHelloArgument.Truncate();
238 }
239 return NS_OK;
240 }
241
242 NS_IMETHODIMP
GetAuthMethod(int32_t * authMethod)243 nsSmtpServer::GetAuthMethod(int32_t* authMethod) {
244 NS_ENSURE_ARG_POINTER(authMethod);
245 getIntPrefWithDefault("authMethod", authMethod, 3);
246 return NS_OK;
247 }
248
getIntPrefWithDefault(const char * prefName,int32_t * val,int32_t defVal)249 void nsSmtpServer::getIntPrefWithDefault(const char* prefName, int32_t* val,
250 int32_t defVal) {
251 nsresult rv = mPrefBranch->GetIntPref(prefName, val);
252 if (NS_SUCCEEDED(rv)) return;
253
254 rv = mDefPrefBranch->GetIntPref(prefName, val);
255 if (NS_FAILED(rv))
256 // last resort
257 *val = defVal;
258 }
259
260 NS_IMETHODIMP
SetAuthMethod(int32_t authMethod)261 nsSmtpServer::SetAuthMethod(int32_t authMethod) {
262 return mPrefBranch->SetIntPref("authMethod", authMethod);
263 }
264
265 NS_IMETHODIMP
GetUsername(nsACString & aUsername)266 nsSmtpServer::GetUsername(nsACString& aUsername) {
267 nsCString result;
268 nsresult rv = mPrefBranch->GetCharPref("username", result);
269 if (NS_FAILED(rv))
270 aUsername.Truncate();
271 else
272 aUsername = result;
273 return NS_OK;
274 }
275
276 NS_IMETHODIMP
SetUsername(const nsACString & aUsername)277 nsSmtpServer::SetUsername(const nsACString& aUsername) {
278 // Need to take care of few things if we're changing the username.
279 nsCString oldName;
280 nsresult rv = GetUsername(oldName);
281 NS_ENSURE_SUCCESS(rv, rv);
282
283 if (!oldName.Equals(aUsername)) {
284 rv = OnUserOrHostNameChanged(oldName, aUsername, false);
285 NS_ENSURE_SUCCESS(rv, rv);
286 }
287
288 if (!aUsername.IsEmpty())
289 return mPrefBranch->SetCharPref("username", aUsername);
290
291 // If the pref value is already empty, ClearUserPref will return
292 // NS_ERROR_UNEXPECTED, so don't check the rv here.
293 (void)mPrefBranch->ClearUserPref("username");
294 return NS_OK;
295 }
296
297 NS_IMETHODIMP
GetClientid(nsACString & aClientid)298 nsSmtpServer::GetClientid(nsACString& aClientid) {
299 nsresult rv;
300 rv = mPrefBranch->GetCharPref("clientid", aClientid);
301 if (NS_FAILED(rv)) {
302 rv = mDefPrefBranch->GetCharPref("clientid", aClientid);
303 if (NS_FAILED(rv)) aClientid.Truncate();
304 }
305 return NS_OK;
306 }
307
308 NS_IMETHODIMP
SetClientid(const nsACString & aClientid)309 nsSmtpServer::SetClientid(const nsACString& aClientid) {
310 if (!aClientid.IsEmpty())
311 return mPrefBranch->SetCharPref("clientid", aClientid);
312
313 // If the pref value is already empty, ClearUserPref will return
314 // NS_ERROR_UNEXPECTED, so don't check the rv here.
315 mPrefBranch->ClearUserPref("clientid");
316 return NS_OK;
317 }
318
GetClientidEnabled(bool * aClientidEnabled)319 NS_IMETHODIMP nsSmtpServer::GetClientidEnabled(bool* aClientidEnabled) {
320 NS_ENSURE_ARG_POINTER(aClientidEnabled);
321 nsresult rv;
322 rv = mPrefBranch->GetBoolPref("clientidEnabled", aClientidEnabled);
323 if (NS_FAILED(rv)) {
324 rv = mDefPrefBranch->GetBoolPref("clientidEnabled", aClientidEnabled);
325 if (NS_FAILED(rv)) *aClientidEnabled = false;
326 }
327 return NS_OK;
328 }
329
SetClientidEnabled(bool aClientidEnabled)330 NS_IMETHODIMP nsSmtpServer::SetClientidEnabled(bool aClientidEnabled) {
331 return mPrefBranch->SetBoolPref("clientidEnabled", aClientidEnabled);
332 }
333
334 NS_IMETHODIMP
GetPassword(nsAString & aPassword)335 nsSmtpServer::GetPassword(nsAString& aPassword) {
336 if (m_password.IsEmpty() && !m_logonFailed) {
337 // try to avoid prompting the user for another password. If the user has set
338 // the appropriate pref, we'll use the password from an incoming server, if
339 // the user has already logged onto that server.
340
341 // if this is set, we'll only use this, and not the other prefs
342 // user_pref("mail.smtpserver.smtp1.incomingAccount", "server1");
343
344 // if this is set, we'll accept an exact match of user name and server
345 // user_pref("mail.smtp.useMatchingHostNameServer", true);
346
347 // if this is set, and we don't find an exact match of user and host name,
348 // we'll accept a match of username and domain, where domain
349 // is everything after the first '.'
350 // user_pref("mail.smtp.useMatchingDomainServer", true);
351
352 nsCString accountKey;
353 bool useMatchingHostNameServer = false;
354 bool useMatchingDomainServer = false;
355 mPrefBranch->GetCharPref("incomingAccount", accountKey);
356
357 nsCOMPtr<nsIMsgAccountManager> accountManager =
358 do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID);
359 nsCOMPtr<nsIMsgIncomingServer> incomingServerToUse;
360 if (accountManager) {
361 if (!accountKey.IsEmpty())
362 accountManager->GetIncomingServer(accountKey,
363 getter_AddRefs(incomingServerToUse));
364 else {
365 nsresult rv;
366 nsCOMPtr<nsIPrefBranch> prefBranch(
367 do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
368 NS_ENSURE_SUCCESS(rv, rv);
369 prefBranch->GetBoolPref("mail.smtp.useMatchingHostNameServer",
370 &useMatchingHostNameServer);
371 prefBranch->GetBoolPref("mail.smtp.useMatchingDomainServer",
372 &useMatchingDomainServer);
373 if (useMatchingHostNameServer || useMatchingDomainServer) {
374 nsCString userName;
375 nsCString hostName;
376 GetHostname(hostName);
377 GetUsername(userName);
378 if (useMatchingHostNameServer)
379 // pass in empty type and port=0, to match imap and pop3.
380 accountManager->FindRealServer(userName, hostName, EmptyCString(),
381 0,
382 getter_AddRefs(incomingServerToUse));
383 int32_t dotPos = -1;
384 if (!incomingServerToUse && useMatchingDomainServer &&
385 (dotPos = hostName.FindChar('.')) != kNotFound) {
386 hostName.Cut(0, dotPos);
387 nsTArray<RefPtr<nsIMsgIncomingServer>> allServers;
388 accountManager->GetAllServers(allServers);
389 for (auto server : allServers) {
390 if (server) {
391 nsCString serverUserName;
392 nsCString serverHostName;
393 server->GetRealUsername(serverUserName);
394 server->GetRealHostName(serverHostName);
395 if (serverUserName.Equals(userName)) {
396 int32_t serverDotPos = serverHostName.FindChar('.');
397 if (serverDotPos != kNotFound) {
398 serverHostName.Cut(0, serverDotPos);
399 if (serverHostName.Equals(hostName)) {
400 incomingServerToUse = server;
401 break;
402 }
403 }
404 }
405 }
406 }
407 }
408 }
409 }
410 }
411 if (incomingServerToUse) return incomingServerToUse->GetPassword(aPassword);
412 }
413 aPassword = m_password;
414 return NS_OK;
415 }
416
417 NS_IMETHODIMP
VerifyLogon(nsIUrlListener * aUrlListener,nsIMsgWindow * aMsgWindow,nsIURI ** aURL)418 nsSmtpServer::VerifyLogon(nsIUrlListener* aUrlListener,
419 nsIMsgWindow* aMsgWindow, nsIURI** aURL) {
420 nsresult rv;
421 nsCOMPtr<nsISmtpService> smtpService(
422 do_GetService(NS_SMTPSERVICE_CONTRACTID, &rv));
423 NS_ENSURE_SUCCESS(rv, rv);
424 return smtpService->VerifyLogon(this, aUrlListener, aMsgWindow, aURL);
425 }
426
427 NS_IMETHODIMP
SetPassword(const nsAString & aPassword)428 nsSmtpServer::SetPassword(const nsAString& aPassword) {
429 m_password = aPassword;
430 return NS_OK;
431 }
432
GetPasswordWithoutUI()433 nsresult nsSmtpServer::GetPasswordWithoutUI() {
434 nsresult rv;
435 nsCOMPtr<nsILoginManager> loginMgr(
436 do_GetService(NS_LOGINMANAGER_CONTRACTID, &rv));
437 NS_ENSURE_SUCCESS(rv, rv);
438
439 NS_ConvertASCIItoUTF16 serverUri(GetServerURIInternal(false));
440
441 nsTArray<RefPtr<nsILoginInfo>> logins;
442 rv = loginMgr->FindLogins(serverUri, EmptyString(), serverUri, logins);
443 // Login manager can produce valid fails, e.g. NS_ERROR_ABORT when a user
444 // cancels the master password dialog. Therefore handle that here, but don't
445 // warn about it.
446 if (NS_FAILED(rv)) return rv;
447 uint32_t numLogins = logins.Length();
448
449 // Don't abort here, if we didn't find any or failed, then we'll just have
450 // to prompt.
451 if (numLogins > 0) {
452 nsCString serverCUsername;
453 rv = GetUsername(serverCUsername);
454 NS_ConvertASCIItoUTF16 serverUsername(serverCUsername);
455
456 nsString username;
457 for (uint32_t i = 0; i < numLogins; ++i) {
458 rv = logins[i]->GetUsername(username);
459 NS_ENSURE_SUCCESS(rv, rv);
460
461 if (username.Equals(serverUsername)) {
462 nsString password;
463 rv = logins[i]->GetPassword(password);
464 NS_ENSURE_SUCCESS(rv, rv);
465
466 m_password = password;
467 break;
468 }
469 }
470 }
471 return NS_OK;
472 }
473
474 NS_IMETHODIMP
GetPasswordWithUI(const char16_t * aPromptMessage,const char16_t * aPromptTitle,nsIAuthPrompt * aDialog,nsAString & aPassword)475 nsSmtpServer::GetPasswordWithUI(const char16_t* aPromptMessage,
476 const char16_t* aPromptTitle,
477 nsIAuthPrompt* aDialog, nsAString& aPassword) {
478 if (!m_password.IsEmpty()) return GetPassword(aPassword);
479
480 // We need to get a password, but see if we can get it from the password
481 // manager without requiring a prompt.
482 nsresult rv = GetPasswordWithoutUI();
483 if (rv == NS_ERROR_ABORT) return NS_MSG_PASSWORD_PROMPT_CANCELLED;
484
485 // Now re-check if we've got a password or not, if we have, then we
486 // don't need to prompt the user.
487 if (!m_password.IsEmpty()) {
488 aPassword = m_password;
489 return NS_OK;
490 }
491
492 NS_ENSURE_ARG_POINTER(aDialog);
493
494 // PromptPassword needs the username as well.
495 nsCString serverUri(GetServerURIInternal(true));
496
497 bool okayValue = true;
498
499 rv = aDialog->PromptPassword(aPromptTitle, aPromptMessage,
500 NS_ConvertASCIItoUTF16(serverUri).get(),
501 nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
502 getter_Copies(aPassword), &okayValue);
503 NS_ENSURE_SUCCESS(rv, rv);
504
505 // If the user pressed cancel, just return an empty string.
506 if (!okayValue) {
507 aPassword.Truncate();
508 return NS_MSG_PASSWORD_PROMPT_CANCELLED;
509 }
510 rv = SetPassword(aPassword);
511 NS_ENSURE_SUCCESS(rv, rv);
512
513 return NS_OK;
514 }
515
516 NS_IMETHODIMP
GetUsernamePasswordWithUI(const char16_t * aPromptMessage,const char16_t * aPromptTitle,nsIAuthPrompt * aDialog,nsACString & aUsername,nsAString & aPassword)517 nsSmtpServer::GetUsernamePasswordWithUI(const char16_t* aPromptMessage,
518 const char16_t* aPromptTitle,
519 nsIAuthPrompt* aDialog,
520 nsACString& aUsername,
521 nsAString& aPassword) {
522 nsresult rv;
523 if (!m_password.IsEmpty()) {
524 rv = GetUsername(aUsername);
525 NS_ENSURE_SUCCESS(rv, rv);
526
527 return GetPassword(aPassword);
528 }
529
530 NS_ENSURE_ARG_POINTER(aDialog);
531
532 nsCString serverUri;
533 rv = GetServerURI(serverUri);
534 NS_ENSURE_SUCCESS(rv, rv);
535
536 nsString uniUsername;
537 bool okayValue = true;
538
539 rv = aDialog->PromptUsernameAndPassword(
540 aPromptTitle, aPromptMessage, NS_ConvertASCIItoUTF16(serverUri).get(),
541 nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY, getter_Copies(uniUsername),
542 getter_Copies(aPassword), &okayValue);
543 NS_ENSURE_SUCCESS(rv, rv);
544
545 // If the user pressed cancel, just return empty strings.
546 if (!okayValue) {
547 aUsername.Truncate();
548 aPassword.Truncate();
549 return rv;
550 }
551
552 // We got a username and password back...so remember them.
553 NS_LossyConvertUTF16toASCII username(uniUsername);
554
555 rv = SetUsername(username);
556 NS_ENSURE_SUCCESS(rv, rv);
557
558 rv = SetPassword(aPassword);
559 NS_ENSURE_SUCCESS(rv, rv);
560
561 aUsername = username;
562 return NS_OK;
563 }
564
565 NS_IMETHODIMP
ForgetPassword()566 nsSmtpServer::ForgetPassword() {
567 nsresult rv;
568 nsCOMPtr<nsILoginManager> loginMgr =
569 do_GetService(NS_LOGINMANAGER_CONTRACTID, &rv);
570 NS_ENSURE_SUCCESS(rv, rv);
571
572 // Get the current server URI without the username
573 NS_ConvertASCIItoUTF16 serverUri(GetServerURIInternal(false));
574
575 nsCString serverCUsername;
576 rv = GetUsername(serverCUsername);
577 NS_ENSURE_SUCCESS(rv, rv);
578
579 NS_ConvertUTF8toUTF16 serverUsername(serverCUsername);
580
581 nsTArray<RefPtr<nsILoginInfo>> logins;
582 rv = loginMgr->FindLogins(serverUri, EmptyString(), serverUri, logins);
583 NS_ENSURE_SUCCESS(rv, rv);
584
585 // There should only be one-login stored for this url, however just in case
586 // there isn't.
587 nsString username;
588 for (uint32_t i = 0; i < logins.Length(); ++i) {
589 if (NS_SUCCEEDED(logins[i]->GetUsername(username)) &&
590 username.Equals(serverUsername)) {
591 // If this fails, just continue, we'll still want to remove the password
592 // from our local cache.
593 loginMgr->RemoveLogin(logins[i]);
594 }
595 }
596
597 rv = SetPassword(EmptyString());
598 m_logonFailed = true;
599 return rv;
600 }
601
602 NS_IMETHODIMP
GetServerURI(nsACString & aResult)603 nsSmtpServer::GetServerURI(nsACString& aResult) {
604 aResult = GetServerURIInternal(true);
605 return NS_OK;
606 }
607
GetServerURIInternal(const bool aIncludeUsername)608 nsCString nsSmtpServer::GetServerURIInternal(const bool aIncludeUsername) {
609 nsCString uri("smtp://"_ns);
610 nsresult rv;
611
612 if (aIncludeUsername) {
613 nsCString username;
614 rv = GetUsername(username);
615
616 if (NS_SUCCEEDED(rv) && !username.IsEmpty()) {
617 nsCString escapedUsername;
618 MsgEscapeString(username, nsINetUtil::ESCAPE_XALPHAS, escapedUsername);
619 // not all servers have a username
620 uri.Append(escapedUsername);
621 uri.Append('@');
622 }
623 }
624
625 nsCString hostname;
626 rv = GetHostname(hostname);
627
628 if (NS_SUCCEEDED(rv) && !hostname.IsEmpty()) {
629 nsCString escapedHostname;
630 MsgEscapeString(hostname, nsINetUtil::ESCAPE_URL_PATH, escapedHostname);
631 // not all servers have a hostname
632 uri.Append(escapedHostname);
633 }
634
635 return uri;
636 }
637
638 NS_IMETHODIMP
ClearAllValues()639 nsSmtpServer::ClearAllValues() {
640 nsTArray<nsCString> prefNames;
641 nsresult rv = mPrefBranch->GetChildList("", prefNames);
642 NS_ENSURE_SUCCESS(rv, rv);
643
644 for (auto& prefName : prefNames) {
645 mPrefBranch->ClearUserPref(prefName.get());
646 }
647
648 return NS_OK;
649 }
650