/// <summary>
/// 取得授權的項目
/// </summary>
static string[] Scopes = { GmailService.Scope.GmailSend };
// 和登入 google 的帳號無關
// 任意值,若未來有使用者認証,可使用使用者編號或登入帳號。
string Username = "ABC";
/// <summary>
/// 存放 client_secret 和 credential 的地方
/// </summary>
string SecretPath = @"D:\project\GmailTest\Data\Secrets";
/// <summary>
/// 認証完成後回傳的網址, 必需和 OAuth 2.0 Client Id 中填寫的 "已授權的重新導向 URI" 相同。
/// </summary>
string RedirectUri = $"https://localhost:44340/Home/AuthReturn";
/// <summary>
/// 取得認証用的網址
/// </summary>
/// <returns></returns>
public async Task<string> GetAuthUrl()
{
using (var stream = new FileStream(Path.Combine(SecretPath, "client_secret.json"), FileMode.Open, FileAccess.Read))
{
FileDataStore dataStore = null;
var credentialRoot = Path.Combine(SecretPath, "Credentials");
if (!Directory.Exists(credentialRoot))
{
Directory.CreateDirectory(credentialRoot);
}
//存放 credential 的地方,每個 username 會建立一個目錄。
string filePath = Path.Combine(credentialRoot, Username);
dataStore = new FileDataStore(filePath);
IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = GoogleClientSecrets.Load(stream).Secrets,
Scopes = Scopes,
DataStore = dataStore
});
var authResult = await new AuthorizationCodeWebApp(flow, RedirectUri, Username)
.AuthorizeAsync(Username, CancellationToken.None);
return authResult.RedirectUri;
}
}
public async Task<string> AuthReturn(AuthorizationCodeResponseUrl authorizationCode)
{
string[] scopes = new[] { GmailService.Scope.GmailSend };
using (var stream = new FileStream(Path.Combine(SecretPath, "client_secret.json"), FileMode.Open, FileAccess.Read))
{
//確認 credential 的目錄已建立.
var credentialRoot = Path.Combine(SecretPath, "Credentials");
if (!Directory.Exists(credentialRoot))
{
Directory.CreateDirectory(credentialRoot);
}
//暫存憑証用目錄
string tempPath = Path.Combine(credentialRoot, authorizationCode.State);
IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(
new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = GoogleClientSecrets.Load(stream).Secrets,
Scopes = scopes,
DataStore = new FileDataStore(tempPath)
});
//這個動作應該是要把 code 換成 token
await flow.ExchangeCodeForTokenAsync(Username, authorizationCode.Code, RedirectUri, CancellationToken.None).ConfigureAwait(false);
if (!string.IsNullOrWhiteSpace(authorizationCode.State))
{
string newPath = Path.Combine(credentialRoot, Username);
if (tempPath.ToLower() != newPath.ToLower())
{
if (Directory.Exists(newPath))
Directory.Delete(newPath, true);
Directory.Move(tempPath, newPath);
}
}
return "OK";
}
}
public async Task<bool> SendTestMail()
{
var service = await GetGmailService();
GmailMessage message = new GmailMessage();
message.Subject = "標題";
message.Body = $"<h1>內容</h1>";
message.FromAddress = "bikehsu@gmail.com";
message.IsHtml = true;
message.ToRecipients = "bikehsu@gmail.com";
message.Attachments = new List<Attachment>();
string filePath = @"C:\Users\bike\Pictures\Vegetable_pumpkin.jpg"; //要附加的檔案
Attachment attachment1 = new Attachment(filePath);
message.Attachments.Add(attachment1);
SendEmail(message, service);
Console.WriteLine("OK");
return true;
}
async Task<GmailService> GetGmailService()
{
UserCredential credential = null;
var credentialRoot = Path.Combine(SecretPath, "Credentials");
if (!Directory.Exists(credentialRoot))
{
Directory.CreateDirectory(credentialRoot);
}
string filePath = Path.Combine(credentialRoot, Username);
using (var stream = new FileStream(Path.Combine(SecretPath, "client_secret.json"), FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
Username,
CancellationToken.None,
new FileDataStore(filePath));
}
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Send Mail",
});
return service;
}
public class GmailMessage
{
public string FromAddress { get; set; }
public string ToRecipients { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
public bool IsHtml { get; set; }
public List<System.Net.Mail.Attachment> Attachments { get; set; }
}
public static void SendEmail(GmailMessage email, GmailService service)
{
var mailMessage = new System.Net.Mail.MailMessage();
mailMessage.From = new System.Net.Mail.MailAddress(email.FromAddress);
mailMessage.To.Add(email.ToRecipients);
mailMessage.ReplyToList.Add(email.FromAddress);
mailMessage.Subject = email.Subject;
mailMessage.Body = email.Body;
mailMessage.IsBodyHtml = email.IsHtml;
if (email.Attachments != null)
{
foreach (System.Net.Mail.Attachment attachment in email.Attachments)
{
mailMessage.Attachments.Add(attachment);
}
}
var mimeMessage = MimeKit.MimeMessage.CreateFromMailMessage(mailMessage);
var gmailMessage = new Google.Apis.Gmail.v1.Data.Message
{
Raw = Encode(mimeMessage)
};
Google.Apis.Gmail.v1.UsersResource.MessagesResource.SendRequest request = service.Users.Messages.Send(gmailMessage, "me");
request.Execute();
}
public static string Encode(MimeMessage mimeMessage)
{
using (MemoryStream ms = new MemoryStream())
{
mimeMessage.WriteTo(ms);
return Convert.ToBase64String(ms.GetBuffer())
.TrimEnd('=')
.Replace('+', '-')
.Replace('/', '_');
}
}
-- To allow advanced options to be changed.開啟進階選項
EXEC sp_configure 'show advanced options', 1
GO
-- To update the currently configured value for advanced options.執行動作
RECONFIGURE
GO
-- To enable the feature.開啟xp_cmdshell功能
EXEC sp_configure 'xp_cmdshell', 1
GO
-- To update the currently configured value for this feature.執行動作
RECONFIGURE
GO
DECLARE @DBPath nvarchar(120)
--指定磁碟機Z的路徑為\\192.168.8.201\SQLBackupLeon
exec master..xp_cmdshell 'net use z: \\192.168.8.201\SQLBackupLeon 密碼 /user:帳號'
--指定備份路徑檔名
SET @DBPath = 'Z:\' + 'ReikoTEST' + '_' + Convert(varchar(10),Getdate(),112) + Replace(Convert(varchar(8),Getdate(),108),':','') + '.bak'
--DATENAME(Weekday,GETDATE())=>會顯示為"星期N"
--SET @DBPath = 'Z:\' + 'Leon' + '_' + DATENAME(Weekday,GETDATE()) + '.bak'
--備份資料庫ReikoTEST到路徑檔名
BACKUP DATABASE ReikoTEST TO DISK = @DBPath
--刪除磁碟機Z
exec master..xp_cmdshell 'net use Z: /delete'
GO
-- To enable the feature.關閉xp_cmdshell功能
EXEC sp_configure 'xp_cmdshell', 0
GO
-- To update the currently configured value for this feature.執行動作
RECONFIGURE
GO
-- To allow advanced options to be changed.關閉進階選項
EXEC sp_configure 'show advanced options', 0
GO
-- To update the currently configured value for advanced options.執行動作
RECONFIGURE
GO
Principal(來源), Mirror(鏡像), Witness(見證,非必要,系統出現錯誤時,自動切換資料庫)
上方三個資料庫需使用相同版本
/*查資料庫版本號*/
SELECT SERVERPROPERTY('productversion'), SERVERPROPERTY ('productlevel'),SERVERPROPERTY ('edition')
參考資料:
MS SQL Server 2008_容錯轉移_資料庫鏡像實作
Simple Step by Step Database Mirroring
SQL Server 2008 的執行個體之間傳送登入和密碼
Troubleshooting Database Mirroring Error 1418
Microsoft SQL 2008 SERVER -- Fix : Error: 1418 Mirroring
/*
DB: Principal
Step 1, 備份來源資料庫
*/
backup database reikoTest to disk='D:\MirrorTEST_Full.bak'
with format
go
backup log reikoTest to disk='D:\MirrorTEST_log.bak'
go
/*
DB: Mirror
Step 2, 建立mirror資料庫
*/
Create database ReikoTEST
go
restore database ReikoTEST from disk='D:\MirrorTEST_Full.bak'
with replace, norecovery
go
restore log ReikoTESt from disk='D:\MirrorTEST_log.bak'
with norecovery
go
/*
DB: Principal
Step 3, 建立SQL Server 2008 的執行個體之間傳送登入和密碼
注意 這個指令碼會在 master 資料庫中建立兩個預存程序。這兩個預存程序名為 sp_hexadecimal 預存程序和 sp_help_revlogin 預存程序。
※第一次建立mirror時(預存程序不存在時),才需執行本指令
*/
SQL指令碼
/*
DB: Principal
Step 4, 查詢傳送登入帳號和密碼
sp_help_revlogin 預存程序所產生的輸出指令碼是登入指令碼。這個登入指令碼會建立具有原始「安全性識別碼」(SID) 和原始密碼的登入。
*/
EXEC sp_help_revlogin
/*
執行後,複製要使用的帳號,至mirror資料庫執行
ex.
-- Login:reiko
CREATE LOGIN [reiko] WITH PASSWORD = 0x010036D88E850F3F29E70120CB4CD2DEE7CBAD1AB83AA4A6A927 HASHED, SID = 0x495A943A23B12C48A43C39776B879A49, DEFAULT_DATABASE = [master], CHECK_POLICY = OFF, CHECK_EXPIRATION = OFF
*/
/*
DB: Mirror
Step 5, 建立傳送登入帳號和密碼
刪掉DEFAULT_DATABASE = [master],(上方紅字部份)
ex.
-- Login:reiko
CREATE LOGIN [reiko] WITH PASSWORD = 0x010036D88E850F3F29E70120CB4CD2DEE7CBAD1AB83AA4A6A927 HASHED, SID = 0x495A943A23B12C48A43C39776B879A49, CHECK_POLICY = OFF, CHECK_EXPIRATION = OFF
*/
-- Login:reiko
CREATE LOGIN [reiko] WITH PASSWORD = 0x010036D88E850F3F29E70120CB4CD2DEE7CBAD1AB83AA4A6A927 HASHED, SID = 0x495A943A23B12C48A43C39776B879A49, CHECK_POLICY = OFF, CHECK_EXPIRATION = OFF